AD BasicOps
Edit this on GitLab
AD BasicOps Sample Application (SSK 1.x)
Overview
The AD BasicOps sample application demonstrates how to configure and read analog-to-digital channels using the NAI Software Support Kit (SSK 1.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, and managing saturation thresholds.
This sample supports the following AD module types: AD1 through AD6 and ADE through ADG. 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.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an AD module installed (AD1–AD6 or ADE–ADG).
-
SSK 1.x installed on your development host.
-
The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.
How to Run
Launch the AD_BasicOps 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.
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 1.x startup flow:
-
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. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()so downstream code can adapt to the specific AD variant installed.
#if defined (__VXWORKS__)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t module = 0;
uint32_t modId = 0u;
int32_t moduleCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
naiapp_query_ModuleNumber(moduleCount, 1, &module);
modId = naibrd_GetModuleID(cardIndex, module);
bQuit = ADBasicOps_run(cardIndex, module, modId);
}
printf("Type the Enter key to exit the program: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms the entry point is main(). On VxWorks the entry point is AD_BasicOps() — the SSK 1.x build system selects the correct variant via a preprocessor guard:
#if defined (__VXWORKS__)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif
The startup flow is the same in both cases:
-
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. -
Enter a loop that queries for card index and module slot.
-
Call
ADBasicOps_run()to enter the interactive command loop for the selected module. -
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:
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 = 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 callingnaibrd_AD_GetChannelCount()with the module ID. -
modId— the module identifier returned bynaibrd_GetModuleID(). 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:
static bool_t ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modId)
{
bool_t bQuit = FALSE;
bool_t bCmdFound = FALSE;
int32_t cmd;
naiapp_AppParameters_t ad_basicops_params;
p_naiapp_AppParameters_t ad_basicOps_params = &ad_basicops_params;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
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 = 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);
printf("\n\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
{
printf("Invalid command entered\n");
}
}
}
} while (!bQuit);
return 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 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 |
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_SetRange() 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_GetPolarityRange() (defined in nai_ad_utils.c) 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.
nai_ad_range_mode_t polarity = NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR;
float64_t range = 0.0;
nai_ad_mode_t mode = NAI_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_SetRange(cardIndex, module, channel, polarity, range);
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
channel— the channel to configure. -
polarity— unipolar (NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR) or 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.
|
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, NAI_AD_MODE_VOLTAGE);
/* Set a single channel to current mode */
status = naibrd_AD_SetMode(cardIndex, module, channel, NAI_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, NAI_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:
NAI_AD_MODE_VOLTAGEorNAI_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_SetLatch(). 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. This is a module-wide operation — there is no per-channel latch control.
bool_t latched = TRUE;
/* Latch all channel readings on the module */
naibrd_AD_SetLatch(cardIndex, module, latched);
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
latched—TRUEto latch (freeze) all channel readings simultaneously,FALSEto 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_SetBreakFrequency(). 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_SetBreakFrequency(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_SetChannelState(). 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_SetChannelState(cardIndex, module, channel, TRUE);
/* Disable a single channel */
status = naibrd_AD_SetChannelState(cardIndex, module, channel, 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_SetChannelState(cardIndex, module, channel, TRUE);
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
channel— the channel to enable or disable. -
The fourth parameter —
TRUEto activate the channel,FALSEto deactivate it.
|
Note
|
This function is AD4 only. On all other AD modules the API returns NAI_ERROR_NOT_SUPPORTED.
|
|
Important
|
Common Errors
|
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_SetTestEnable() to turn the D0 test on or off, and naibrd_AD_ConfigureD0Test() 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 always 10V, 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_SetTestEnable(cardIndex, module, NAI_AD_D0_TEST, TRUE);
/* Configure D0 test: set polarity, range, and test level */
nai_ad_range_mode_t polarity = NAI_AD_RANGE_MODE_BIPOLAR;
float64_t D0Range = 10.0;
float64_t testLevel = 5.0;
naibrd_AD_ConfigureD0Test(cardIndex, module, polarity, D0Range, testLevel);
To disable the D0 test when you are finished:
naibrd_AD_SetTestEnable(cardIndex, module, NAI_AD_D0_TEST, FALSE);
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
NAI_AD_D0_TEST— selects the D0 test type. -
polarity—NAI_AD_RANGE_MODE_UNIPOLARorNAI_AD_RANGE_MODE_BIPOLAR. -
D0Range— the full-scale range for the D0 test (always 10V for voltage-mode modules). -
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, 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_GetModulePBITComplete() to check whether PBIT has run, then iterate over all channels calling naibrd_AD_GetStatus() with NAI_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_GetModulePBITComplete(cardIndex, module, channel, &pbitComplete);
if (pbitComplete)
{
/* Step 2: Read BIT status for each channel */
for (channel = 1; channel <= channelCount; channel++)
{
naibrd_AD_GetStatus(cardIndex, module, channel,
NAI_AD_STATUS_BIT_LATCHED, &bitFailed);
if (bitFailed)
printf("Channel %d: BIT FAILED\n", channel);
else
printf("Channel %d: BIT Passed\n", channel);
}
}
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
channel— passed to the PBIT completion check (any valid channel). -
pbitComplete— set toTRUEif PBIT has finished,FALSEotherwise. -
NAI_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_SetModuleBITErrorThreshold(). To read the current threshold, call naibrd_GetModuleBITErrorThreshold(). To reset BIT counters on a per-channel basis, call naibrd_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.
uint32_t bitThreshold = 0u;
/* Set BIT error threshold */
naibrd_SetModuleBITErrorThreshold(cardIndex, module, 10);
/* Read back the current threshold */
naibrd_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_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_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, TRUE);
/* Disable status reporting on a channel */
naibrd_AD_SetChanStatusEnable(cardIndex, module, channel, 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 —
TRUEto enable status reporting,FALSEto 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
|
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 = 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 toTRUEif the module supports floating-point conversion,FALSEotherwise. -
The third parameter to
naibrd_SetFloatingPointModeEnable()—0x1to enable,0x0to 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_SetFloatingPointOffset(). 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 = 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_SetFloatingPointOffset(cardIndex, module, channel, offset);
}
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
channel— the channel to configure. -
offset— the offset value to apply. This is afloat64_tand 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_SetFloatingPointScaleFactor(). 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 = 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_SetFloatingPointScaleFactor(cardIndex, module, channel, scale);
}
-
cardIndex— identifies the board. -
module— the slot containing the AD module. -
channel— the channel to configure. -
scale— the scale factor to apply. This is afloat64_t.
|
Important
|
Common Errors
|
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_GetModuleRev() to retrieve the module’s FPGA revision and compares it against a minimum threshold that varies by module family (AD1-AD3, AD4-AD6, or ADE-ADG).
uint32_t fpgaRev = 0u;
uint32_t modprocrev;
bool_t satAvailable = FALSE;
/* Retrieve the module's FPGA revision */
naibrd_GetModuleRev(cardIndex, module, &modprocrev, &fpgaRev);
/* Compare fpgaRev against the minimum revision for your module family */
if (fpgaRev >= minimumSupportedRev)
satAvailable = 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,
NAI_AD_SATURATION_CONTROL_LOW, lowThreshold);
/* Set the high saturation threshold for a channel */
naibrd_AD_SetSaturationLevel(cardIndex, module, channel,
NAI_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:
NAI_AD_SATURATION_CONTROL_LOWorNAI_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,
NAI_AD_SATURATION_CONTROL_LOW, TRUE);
/* Enable high-level saturation detection on a channel */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_HIGH, TRUE);
To disable detection, pass FALSE instead of TRUE:
/* Disable low-level saturation detection */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_LOW, FALSE);
/* Disable high-level saturation detection */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_HIGH, 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:
NAI_AD_SATURATION_CONTROL_LOWorNAI_AD_SATURATION_CONTROL_HIGH. -
The fifth parameter —
TRUEto enable detection,FALSEto 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 = FALSE;
bool_t satHighEnable = FALSE;
/* Read saturation threshold levels */
naibrd_AD_GetSaturationLevel(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_LOW, &satLowLevel);
naibrd_AD_GetSaturationLevel(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_HIGH, &satHighLevel);
/* Read saturation enable states */
naibrd_AD_GetSaturationControl(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_LOW, &satLowEnable);
naibrd_AD_GetSaturationControl(cardIndex, module, channel,
NAI_AD_SATURATION_CONTROL_HIGH, &satHighEnable);
-
satLowLevel/satHighLevel— the configured threshold voltages. -
satLowEnable/satHighEnable—TRUEif detection is active for that threshold,FALSEotherwise.
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
|
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_GetVoltage(). 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;
nai_ad_range_mode_t polarity = NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR;
uint32_t filterBreakFreq = 0u;
nai_ad_mode_t data_mode = NAI_AD_MODE_VOLTAGE;
for (channel = 1; channel <= maxChannels; channel++)
{
naibrd_AD_GetVoltage(cardIndex, module, channel, &data);
naibrd_AD_GetChannelRaw(cardIndex, module, channel, NAI_AD_CHAN_RAW_DATA, &rawData);
naibrd_AD_GetRange(cardIndex, module, channel, &polarity, &range);
naibrd_AD_GetBreakFrequency(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:
nai_ad_state_t channelActive = NAI_AD_STATE_INACTIVE;
naibrd_AD_GetChannelState(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_GetFloatingPointOffset(cardIndex, module, channel, &offset);
naibrd_AD_GetFloatingPointScaleFactor(cardIndex, module, channel, &scale);
-
naibrd_AD_GetVoltage()— 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_GetRange()— returns both the polarity and the full-scale range for the channel. -
naibrd_AD_GetBreakFrequency()— returns the configured low-pass filter cutoff frequency in Hz. -
naibrd_AD_GetMode()— returns the measurement mode (voltage or current). -
naibrd_AD_GetChannelState()— returns the channel active/inactive state (AD4 only). -
naibrd_AD_GetFloatingPointOffset()/naibrd_AD_GetFloatingPointScaleFactor()— return the hardware floating-point offset and scale factor for the channel.
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_GetStatus() with the appropriate status type to retrieve real-time and latched values. The ADBasicOps_displayStatus() function demonstrates the complete set of status read-back calls:
nai_status_bit_t chanStatusEnabled;
nai_status_bit_t bitStatusRT, bitStatusLT;
nai_status_bit_t openStatusRT, openStatusLT;
nai_status_bit_t summaryStatusRT, summaryStatusLT;
naibrd_AD_GetChanStatusEnable(cardIndex, module, channel, &chanStatusEnabled);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_BIT_REALTIME, &bitStatusRT);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_BIT_LATCHED, &bitStatusLT);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_OPEN_OVERVOLT_REALTIME, &openStatusRT);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_OPEN_OVERVOLT_LATCHED, &openStatusLT);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_SUMMARY_REALTIME, &summaryStatusRT);
naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_SUMMARY_LATCHED, &summaryStatusLT);
The sample displays each status pair in R/L (real-time / latched) format. Here is how to interpret the values:
-
R/L — the first digit is the real-time status, the second is the latched status. Real-time reflects the current condition; latched holds the value until explicitly cleared.
-
0 = normal/pass, 1 = fail/detected — a zero means the condition is not present, a one means it has been detected.
-
BIT status — tests the AD conversion path. A failure indicates that 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 detection typically means the input is disconnected or exceeds the configured range.
-
Summary — an aggregate of all error conditions for the channel. If any individual status is in a fail state, the summary status will also report a fail.
Hex vs. Voltage Toggle
The ADBasicOps_toggleNumDisplay() function switches the displayHex flag, which controls whether the display functions call naibrd_AD_GetVoltage() or naibrd_AD_GetChannelRaw():
if (displayHex)
{
naibrd_AD_GetChannelRaw(cardIndex, module, channel, NAI_AD_CHAN_RAW_DATA, &rawData);
/* Display as hex: 0x00000000 */
}
else
{
naibrd_AD_GetVoltage(cardIndex, module, channel, &data);
/* Display in engineering units: voltage or current */
}
Both calls read the same underlying channel data, but present it differently:
-
naibrd_AD_GetVoltage()returns afloat64_tin 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 auint32_tdisplayed 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 |
Module not detected at selected slot |
No module installed at the specified slot, incorrect module number entered |
Verify hardware configuration and module slot assignment |
|
Feature not available for this module type (e.g., mode switching on non-AD4) 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. |
|
Invalid parameter passed to an API call (e.g., out-of-range value, unsupported polarity) |
Verify input values against your module’s manual specifications |
|
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 |
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 |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — AD_BasicOps.c (SSK 1.x)
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
#include "nai_ad_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ad.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.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 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);
/* Additional Helper Functions */
static void ADBasicOps_displayStatus(int cardIndex, int module, int channel);
/****** 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_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
};
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 },
{"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 },
};
/*****************************************************************************/
/**
* <summary>
* The purpose of the AD_BasicOps is to illustrate the methods to call in the
* naibrd library to perform basic operations with the AD modules for
* configuration setup and reading the channels.
*
* The following system configuration routines from the nai_sys_cfg.c file are
* called to assist with the configuration setup for this program prior to
* calling the naibrd AD routines.
* - ConfigDevice
* - DisplayDeviceCfg
* - GetBoardSNModCfg
* - CheckModule
* </summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t module = 0;
uint32_t modId = 0u;
int32_t moduleCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
naiapp_query_ModuleNumber(moduleCount, 1, &module);
modId = naibrd_GetModuleID(cardIndex, module);
bQuit = ADBasicOps_run(cardIndex, module, modId);
}
printf("Type the Enter key to exit the program: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_run illustrates the channel configuration and prepares the menu
* which will handle user command requests. Returns TRUE if the user enters
* the Quit Command at any point within its scope.
* </summary>
*/
/*****************************************************************************/
static bool_t ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modId)
{
bool_t bQuit = FALSE;
bool_t bCmdFound = FALSE;
int32_t cmd;
naiapp_AppParameters_t ad_basicops_params;
p_naiapp_AppParameters_t ad_basicOps_params = &ad_basicops_params;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
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 = 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);
printf("\n\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
{
printf("Invalid command entered\n");
}
}
}
} while (!bQuit);
return bQuit;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_displayConfigurations illustrates the methods to call in the naibrd library
* to retrieve the basic operation configuration states and status states
* as well as the current voltage reading for all channels.
* </summary>
*/
/*****************************************************************************/
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;
nai_ad_range_mode_t polarity = NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR;
nai_ad_mode_t data_mode = NAI_AD_MODE_VOLTAGE;
nai_ad_state_t channelActive = NAI_AD_STATE_INACTIVE;
char* sChannelState = "";
bool_t latched = FALSE;
bool_t d0TestEnable = FALSE;
nai_ad_range_mode_t d0Polarity = NAI_AD_GEN5_D0_RANGE_MODE_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 = FALSE;
bool_t floatMode = FALSE;
if (modId == NAI_MODULE_ID_AD4)
{
printf("\n\n =================================================================================================================================\n");
printf(" Chan Chan Mode Volt/Curr Range Polarity Break Chan BIT Status Open Status Summary Status FP FP\n");
printf(" State Freq Status (R/L) (R/L) (R/L) Offset Scale\n");
printf(" ---------------------------------------------------------------------------------------------------------------------------------\n");
}
else
{
printf("\n\n ====================================================================================================================\n");
printf(" Chan Voltage Range Polarity Break Chan BIT Status Open Status Summary Status FP FP\n");
printf(" Freq Status (R/L) (R/L) (R/L) Offset Scale\n");
printf(" ----------------------------------------------------------------------------------------------------------------------\n");
}
for (channel = 1; channel <= maxChannels; channel++)
{
/*** Acquire values stored in selected channel ***/
check_status(naibrd_AD_GetMode(cardIndex, module, channel, &data_mode));
printf(" %2d ", channel);
if (modId == NAI_MODULE_ID_AD4)
{
check_status(naibrd_AD_GetChannelState(cardIndex, module, channel, &channelActive));
if (FALSE == channelActive)
{
sChannelState = "INACTIVE";
}
else
{
sChannelState = " ACTIVE ";
}
printf("%8s ", sChannelState);
}
if (displayHex)
{
check_status(naibrd_AD_GetChannelRaw(cardIndex, module, channel, NAI_AD_CHAN_RAW_DATA, &rawData));
if (modId == NAI_MODULE_ID_AD4 && data_mode == NAI_AD_MODE_CURRENT)
{
printf("Current 0x%08X ", rawData);
}
else if (modId == NAI_MODULE_ID_AD4 && data_mode == NAI_AD_MODE_VOLTAGE)
{
printf("Voltage 0x%08X ", rawData);
}
else
{
printf("0x%08X ", rawData);
}
}
else
{
check_status(naibrd_AD_GetVoltage(cardIndex, module, channel, &data));
if (modId == NAI_MODULE_ID_AD4 && data_mode == NAI_AD_MODE_CURRENT)
{
printf("Current %10.6fA ", data);
}
else
{
if (modId == NAI_MODULE_ID_AD4 && data_mode == NAI_AD_MODE_VOLTAGE)
printf("Voltage %10.6fV ", data);
else
printf("%10.6fV ", data);
}
}
check_status(naibrd_AD_GetRange(cardIndex, module, channel, &polarity, &range));
printf("%6.2f ", range);
if (polarity == NAI_AD_RANGE_MODE_UNIPOLAR)
printf("UNIPOLAR");
else if (polarity == NAI_AD_RANGE_MODE_BIPOLAR)
printf("BIPOLAR ");
else
printf("ERROR ");
check_status(naibrd_AD_GetBreakFrequency(cardIndex, module, channel, &filterBreakFreq));
printf("%6u ", filterBreakFreq);
ADBasicOps_displayStatus(cardIndex, module, channel);
check_status(naibrd_GetFloatingPointModeCapability(cardIndex, module, &fpCapable));
if (fpCapable == TRUE)
{
check_status(naibrd_AD_GetFloatingPointOffset(cardIndex, module, channel, &offset));
check_status(naibrd_AD_GetFloatingPointScaleFactor(cardIndex, module, channel, &scale));
printf(" %7.3f %7.3f", offset, scale);
}
else
{
printf(" N/A N/A");
}
printf("\n");
}
printf("\n\nLatch Status (all channels): ");
check_status(naibrd_AD_GetLatch(cardIndex, module, &latched));
if (FALSE == latched)
{
printf("UNLATCHED\n");
}
else
{
printf("LATCHED\n");
}
if (fpCapable == TRUE)
{
check_status(naibrd_GetRunningInFloatingPointMode(cardIndex, module, &floatMode));
if (floatMode == TRUE)
{
printf("Floating-Point Mode: ENABLED\n");
}
else
{
printf("Floating-Point Mode: DISABLED\n");
}
}
if (displayHex)
{
printf("D0 Test (all channels): Internal Test Enable: ");
check_status(naibrd_AD_GetRaw(cardIndex, module, NAI_AD_RAW_TEST_ENABLE, &rawD0TestEnable));
check_status(naibrd_AD_GetRaw(cardIndex, module, NAI_AD_RAW_D0_RANGE_POLARITY, &rawD0Polarity));
check_status(naibrd_AD_GetRaw(cardIndex, module, NAI_AD_RAW_D0_TEST_VALUE, &rawD0TestLevel));
printf("0x%02X, Range/Polarity: 0x%02X, ", rawD0TestEnable, rawD0Polarity);
printf("Voltage Level: 0x%08X\n", rawD0TestLevel);
}
else
{
printf("D0 Test (all channels): ");
check_status(naibrd_AD_GetTestEnable(cardIndex, module, NAI_AD_D0_TEST, &d0TestEnable));
if (FALSE == d0TestEnable)
{
printf("DISABLED\n");
}
else
{
check_status(naibrd_AD_GetD0TestSettings(cardIndex, module, &d0Polarity, &d0Range, &d0TestLevel));
printf("ENABLED, Range:%6.2lfV, Mode: ", d0Range);
if (NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR == d0Polarity)
{
printf("UNIPOLAR");
}
else
{
printf("BIPOLAR");
}
printf(", Voltage Level:%10.6lfV\n", d0TestLevel);
}
}
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setRangePolarity handles the user request to set the configuration states
* of Range and Polarity for the selected channel.
* </summary>
*/
/*****************************************************************************/
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;
nai_ad_range_mode_t polarity = NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR;
bool_t bQuit = FALSE;
nai_ad_mode_t mode = NAI_AD_MODE_VOLTAGE;
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)
{
naibrd_AD_GetMode(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, &mode);
if (FALSE == p_ad_params->displayHex)
{
ADUtils_GetPolarityRange(p_ad_params->cardIndex, p_ad_params->module, mode, &polarity, &range);
naibrd_AD_SetRange(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, polarity, range);
}
else
{
ADModule_GetHexPolarityRange(p_ad_params->cardIndex, p_ad_params->module, &mode, &range);
naibrd_AD_SetRange(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, polarity, range);
}
}
status = NAI_SUCCESS;
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setLatch handles the user request to set the latch on all channel readings.
* </summary>
*/
/*****************************************************************************/
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 = FALSE;
bool_t bQuit = FALSE;
nai_status_t status = NAI_ERROR_UNKNOWN;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (APP_PARAM_COUNT == paramCount)
{
printf("Type 'L' to LATCH, or press any other key to UNLATCH all channels:\n>>");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (toupper(inputBuffer[0]) == 'L')
latched = TRUE;
else
latched = FALSE;
check_status(naibrd_AD_SetLatch(p_ad_params->cardIndex, p_ad_params->module, latched));
}
status = NAI_SUCCESS;
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setMode handles the user request to set the configuration states
* of Mode for the selected channel.
* </summary>
*/
/*****************************************************************************/
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 = FALSE;
int channel;
nai_status_t status = NAI_SUCCESS;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (APP_PARAM_COUNT == paramCount)
{
if (p_ad_params->modId == NAI_MODULE_ID_AD4)
{
printf("\nType 'V' for voltage mode\n");
printf(" 'C' for current mode\n");
printf(" 'VA' to set all chan to voltage mode\n");
printf(" 'CA' to set all chan to current mode\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, NAI_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, NAI_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, NAI_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, NAI_AD_MODE_CURRENT);
}
}
}
printf("Returned status %s\n", nai_GetStatusString(status));
}
}
else
{
printf("Mode selection only available for AD4\n");
status = NAI_ERROR_NOT_SUPPORTED;
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setBreakFreq handles the user request to set the
* filter break frequency for the selected channel.
* </summary>
*/
/*****************************************************************************/
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 = 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));
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_SetBreakFrequency(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
filterBreakFrequency));
}
}
return NAI_SUCCESS;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setActiveChannel handles the user request to set the
* active/inactive state for the selected channel.
* </summary>
*/
/*****************************************************************************/
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 = FALSE;
int32_t channel = 0;
nai_status_t status = NAI_SUCCESS;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (APP_PARAM_COUNT == paramCount)
{
printf("\nType 'A' to set channel to ACTIVE\n");
printf("Type 'I' to set channel to INACTIVE\n");
printf("Type 'CA' to set all channels to ACTIVE\n");
printf("Type 'CI' to set all channels to INACTIVE\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_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, 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_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, 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_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, channel, TRUE);
}
else
{
naibrd_AD_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, channel, TRUE);
}
}
}
else if (toupper(inputBuffer[1]) == 'I')
{
for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
{
if (status == NAI_SUCCESS)
{
status = naibrd_AD_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, channel, FALSE);
}
else
{
naibrd_AD_SetChannelState(p_ad_params->cardIndex, p_ad_params->module, channel, FALSE);
}
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
printf("Returned status %s\n", nai_GetStatusString(status));
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setD0TestEnable handles the user request to set the D0 Test
* Enabled/Disabled State and configure the D0 Test Settings. The only range
* available is the 10V range. Valid range modes are unipolar and bipolar.
* The D0 Test Level can also be set.
* </summary>
*/
/*****************************************************************************/
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 = FALSE;
nai_ad_range_mode_t polarity = NAI_AD_RANGE_MODE_UNIPOLAR;
nai_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)
{
printf("Type 'D' to DISABLE the D0 Test, or press any other key to ENABLE the D0 Test:\n>>");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if ((inputResponseCnt > 0) && (toupper(inputBuffer[0]) == 'D'))
{
check_status(naibrd_AD_SetTestEnable(p_ad_params->cardIndex, p_ad_params->module, NAI_AD_D0_TEST, FALSE));
}
else
{
check_status(naibrd_AD_SetTestEnable(p_ad_params->cardIndex, p_ad_params->module, NAI_AD_D0_TEST, TRUE));
printf("\n\nConfigure the D0 test Polarity and Voltage level.\n");
printf("**NOTE: Channels that are not set to the same Range and Polarity as D0 will not be scaled the same,\n");
printf(" and will show unexpected readings.\n");
printf("D0 range is always 10V, but the Polarity is configurable.\n");
if (p_ad_params->displayHex)
{
printf("\nType Raw D0 Test Range/Polarity Mode to set:\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, NAI_AD_RAW_D0_RANGE_POLARITY,
rawD0RangePolarity));
printf("\nType Raw D0 Test Voltage Level to set:\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, NAI_AD_RAW_D0_TEST_VALUE,
rawD0TestLevel));
}
}
}
else
{
printf("Type 'U' to set the D0 Test Polarity to UNIPOLAR, or press any other key for BIPOLAR:\n>>");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if ((inputResponseCnt > 0) && (toupper(inputBuffer[0]) == 'U'))
{
polarity = NAI_AD_RANGE_MODE_UNIPOLAR;
rawD0RangePolarity = (uint32_t)NAI_AD_GEN5_D0_RANGE_MODE_UNIPOLAR;
}
else
{
polarity = NAI_AD_RANGE_MODE_BIPOLAR;
rawD0RangePolarity = (uint32_t)NAI_AD_GEN5_D0_RANGE_MODE_BIPOLAR;
}
printf("Type the D0 Test Voltage Level you want to set:\n>>");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if ((!bQuit) && (inputResponseCnt > 0))
{
sscanf((const char*)inputBuffer, "%lf", &testLevel);
if ((p_ad_params->modId == NAI_MODULE_ID_AD3) || (p_ad_params->modId == NAI_MODULE_ID_ADG))
{
D0mode = NAI_AD_MODE_CURRENT;
}
else
{
D0mode = NAI_AD_MODE_VOLTAGE;
}
naibrd_AD_ConvertToVoltageRange(p_ad_params->modId, rawD0RangePolarity, &D0mode, &D0Range);
check_status(naibrd_AD_ConfigureD0Test(p_ad_params->cardIndex, p_ad_params->module, polarity, D0Range, testLevel));
}
}
}
}
}
status = NAI_SUCCESS;
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_displayStatus prints to stdin the range mode, BIT status, and Open Status in
* a format thats fits the table produced in displayChannelCfg.
* </summary>
*/
/*****************************************************************************/
static void ADBasicOps_displayStatus(int cardIndex, int module, int channel)
{
nai_status_bit_t bitStatusRT, bitStatusLT;
nai_status_bit_t openStatusRT, openStatusLT;
nai_status_bit_t summaryStatusRT, summaryStatusLT;
nai_status_bit_t chanStatusEnabled;
check_status(naibrd_AD_GetChanStatusEnable(cardIndex, module, channel, &chanStatusEnabled));
printf(" %s ", (chanStatusEnabled == FALSE) ? "NO " : "YES");
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_BIT_REALTIME, &bitStatusRT));
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_BIT_LATCHED, &bitStatusLT));
printf(" %d/%d", (bitStatusRT == NAI_STATUS_BIT_HI ? 1 : 0), (bitStatusLT == NAI_STATUS_BIT_HI ? 1 : 0));
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_OPEN_OVERVOLT_REALTIME, &openStatusRT));
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_OPEN_OVERVOLT_LATCHED, &openStatusLT));
printf(" %d/%d", (openStatusRT == NAI_STATUS_BIT_HI ? 1 : 0), (openStatusLT == NAI_STATUS_BIT_HI ? 1 : 0));
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_SUMMARY_REALTIME, &summaryStatusRT));
check_status(naibrd_AD_GetStatus(cardIndex, module, channel, NAI_AD_STATUS_SUMMARY_LATCHED, &summaryStatusLT));
printf(" %d/%d", (summaryStatusRT == NAI_STATUS_BIT_HI ? 1 : 0), (summaryStatusLT == NAI_STATUS_BIT_HI ? 1 : 0));
}
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 (FALSE == p_ad_params->displayHex)
{
p_ad_params->displayHex = TRUE;
}
else
{
p_ad_params->displayHex = FALSE;
}
status = NAI_SUCCESS;
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* ADBasicOps_CheckPowerOnBIT() Checks to see if the power-on BIT test
* has been run on the module. If the PBIT test has run, it checks the result
* of the test and reports it back.
* </summary>
*/
/**************************************************************************************************************/
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)
{
switch (p_ad_params->modId)
{
case NAI_MODULE_ID_AD1:
case NAI_MODULE_ID_AD2:
case NAI_MODULE_ID_AD3:
case NAI_MODULE_ID_AD4:
case NAI_MODULE_ID_AD5:
case NAI_MODULE_ID_AD6:
case NAI_MODULE_ID_ADE:
case NAI_MODULE_ID_ADF:
case NAI_MODULE_ID_ADG:
{
channelCount = naibrd_AD_GetChannelCount(p_ad_params->modId);
/* Check to see if PBIT ran for the module. */
printf("Checking if the Power-On BIT test has run...\n");
status = naibrd_GetModulePBITComplete(p_ad_params->cardIndex, p_ad_params->module,p_ad_params->channel, &pbitComplete);
printf("PBIT Complete: %s", (pbitComplete) ? "COMPLETED\n" : "NOT COMPLETED\n");
if (pbitComplete)
{
/* Read the BIT status */
printf("Checking the result of the Power-on BIT test...\n");
for (channel = 1; channel <= channelCount; channel++)
{
status = naibrd_AD_GetStatus(p_ad_params->cardIndex, p_ad_params->module, channel, NAI_AD_STATUS_BIT_LATCHED,
&bitFailed);
printf("Ch. %d: %s", channel, bitFailed ? "BIT FAILED\n" : "BIT Passed\n");
}
}
}
break;
default:
printf("\n\n****************************************************\n");
printf("*** This feature is not supported by this module.***\n");
printf("****************************************************\n");
status = NAI_ERROR_NOT_SUPPORTED;
break;
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* ADBasicOps_BITThresholds() allows the user to set and get the BIT error thresholds.
* This is an advanced feature.
* </summary>
*/
/**************************************************************************************************************/
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;
bool_t bQuit = FALSE;
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 NAI_MODULE_ID_AD1:
case NAI_MODULE_ID_AD2:
case NAI_MODULE_ID_AD3:
case NAI_MODULE_ID_AD4:
case NAI_MODULE_ID_AD5:
case NAI_MODULE_ID_AD6:
case NAI_MODULE_ID_ADE:
case NAI_MODULE_ID_ADF:
case NAI_MODULE_ID_ADG:
{
printf("Set or Get BIT Error Threshold? ('S' = Set, 'G' = Get, 'C' = Clear BIT Counter): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (bQuit != FALSE)
{
if (inputBuffer[0] == 'S')
{
printf("\nType the desired BIT Error Threshold (Default = 5): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (bQuit != FALSE)
{
printf("\n");
bitThreshold = atoi((const char*)inputBuffer);
status = naibrd_SetModuleBITErrorThreshold(p_ad_params->cardIndex, p_ad_params->module, bitThreshold);
}
}
else if (inputBuffer[0] == 'G')
{
status = naibrd_GetModuleBITErrorThreshold(p_ad_params->cardIndex, p_ad_params->module, &bitThreshold);
printf("\nBIT Error threshold: %d", bitThreshold);
}
else if (inputBuffer[0] == 'C')
{
int32_t ch;
int32_t channels = naibrd_AD_GetChannelCount(p_ad_params->modId);
printf("\nClearing BIT counters on all channels.\n");
for (ch = 1; ch <= channels; ch++)
status = naibrd_ClearModuleBITLogic(p_ad_params->cardIndex, p_ad_params->module, ch);
}
else
{
printf("\nSelection not recognized.\n");
}
}
}
break;
default:
printf("\n\n****************************************************\n");
printf("*** This feature is not supported by this module.***\n");
printf("****************************************************\n");
status = NAI_ERROR_NOT_SUPPORTED;
break;
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* This function enables/disables the hardware floating-point conversion mode of the DA module, as specified
* by the user.
* </summary>
*/
/**************************************************************************************************************/
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 = FALSE;
bool_t fpCapable = 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 == TRUE)
{
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
{
printf("\n\n****************************************************\n");
printf("*** This feature is not supported by this module.***\n");
printf("****************************************************\n");
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* This function sets the hardware floating-point conversion mode offset for the DA channel specified by the
* user. This function is only applicable when the hardware floating-point conversion mode for the module is
* enabled.
* </summary>
*/
/**************************************************************************************************************/
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 = FALSE;
float64_t offset = 0.0;
bool_t fpCapable = 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 == TRUE)
{
bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
if (!bQuit)
{
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_SetFloatingPointOffset(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, offset));
}
}
}
else
{
printf("\n\n****************************************************\n");
printf("*** This feature is not supported by this module.***\n");
printf("****************************************************\n");
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* This function sets the hardware floating-point conversion mode scale factor for the DA channel specified by
* the user. This function is only applicable when the hardware floating-point conversion mode for the module
* is enabled.
* </summary>
*/
/**************************************************************************************************************/
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 = FALSE;
float64_t scale = 0.0;
bool_t fpCapable = 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 == TRUE)
{
bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
if (!bQuit)
{
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_SetFloatingPointScaleFactor(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, scale));
}
}
}
else
{
printf("\n\n****************************************************\n");
printf("*** This feature is not supported by this module.***\n");
printf("****************************************************\n");
}
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
return status;
}
/**************************************************************************************************************/
/**
* <summary>
* This function Enables\Disables the reporting of the Channel Status. When enabled, the user will get status
* updates. When disabled, the statuses will not report and status-based interrupts will not assert.
* </summary>
*/
/**************************************************************************************************************/
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 = 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)
{
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')) ? TRUE : 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 = FALSE;
bool_t satHighEnable = FALSE;
char* sChannelState = "";
/* Unused params */
modId = 0;
displayHex = 0;
printf("\n\n ============================================================================\n");
printf(" Chan Saturation Low Low Enabled | Saturation High High Enabled\n");
printf(" --------------------------------------------------------------------------------\n");
for (channel = 1; channel <= maxChannels; channel++)
{
/*** Acquire values stored in selected channel ***/
check_status(naibrd_AD_GetSaturationLevel(cardIndex, module, channel, NAI_AD_SATURATION_CONTROL_LOW, &satLowLevel));
check_status(naibrd_AD_GetSaturationLevel(cardIndex, module, channel, NAI_AD_SATURATION_CONTROL_HIGH, &satHighLevel));
check_status(naibrd_AD_GetSaturationControl(cardIndex, module, channel, NAI_AD_SATURATION_CONTROL_LOW, &satLowEnable));
check_status(naibrd_AD_GetSaturationControl(cardIndex, module, channel, NAI_AD_SATURATION_CONTROL_HIGH, &satHighEnable));
printf(" %2d ", channel);
printf("%10.6fV ", satLowLevel);
if (FALSE == satLowEnable)
{
sChannelState = " INACTIVE ";
}
else
{
sChannelState = " ACTIVE ";
}
printf("%12s", sChannelState);
printf("| %10.6fV ", satHighLevel);
if (FALSE == satHighEnable)
{
sChannelState = " INACTIVE ";
}
else
{
sChannelState = " ACTIVE ";
}
printf("%12s\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 = FALSE;
bool_t bCmdFound = FALSE;
int32_t cmd = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (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);
printf("\n\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
{
printf("Invalid command entered\n");
}
}
}
} while (!bQuit);
status = NAI_SUCCESS;
}
else
{
status = NAI_ERROR_INVALID_VALUE;
}
}
else
{
printf("\n\n***Saturation is not supported by this module.***\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)
{
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, NAI_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)
{
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, NAI_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 = 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)
{
printf("Type 'E' to ENABLE Low-Level Saturation, or press any other key to DISABLE it:\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,
NAI_AD_SATURATION_CONTROL_LOW, TRUE));
}
else
{
check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
NAI_AD_SATURATION_CONTROL_LOW, 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 = 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)
{
printf("Type 'E' to ENABLE High-Level Saturation, or press any other key to DISABLE it:\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,
NAI_AD_SATURATION_CONTROL_HIGH, TRUE));
}
else
{
check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
NAI_AD_SATURATION_CONTROL_HIGH, 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 = FALSE;
uint32_t modprocrev;
check_status(naibrd_GetModuleRev(p_ad_params->cardIndex, p_ad_params->module, &modprocrev, &fpgaRev));
/* Unused params */
paramCount = 0;
switch (p_ad_params->modId)
{
case NAI_MODULE_ID_AD1:
case NAI_MODULE_ID_AD2:
case NAI_MODULE_ID_AD3:
supportedRev = NAIAPPS_AD123_SATURATION_SUPPORT_FPGA_REV;
retVal = TRUE;
break;
case NAI_MODULE_ID_AD4:
case NAI_MODULE_ID_AD5:
case NAI_MODULE_ID_AD6:
supportedRev = NAIAPPS_AD456_SATURATION_SUPPORT_FPGA_REV;
retVal = TRUE;
break;
case NAI_MODULE_ID_ADE:
case NAI_MODULE_ID_ADF:
case NAI_MODULE_ID_ADG:
supportedRev = NAIAPPS_ADEFG_SATURATION_SUPPORT_FPGA_REV;
retVal = TRUE;
break;
default:
retVal = FALSE;
break;
}
if ((retVal == TRUE) && (fpgaRev < supportedRev))
{
retVal = FALSE;
}
return retVal;
}