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

DT BasicOps

DT BasicOps Sample Application (SSK 1.x)

Overview

The DT BasicOps sample application demonstrates how to configure and operate discrete (DT) I/O channels using the NAI Software Support Kit (SSK 1.x). Discrete I/O channels are configurable digital lines that can source or sink current at programmable voltage thresholds — they are the hardware interface between your embedded system and external digital signals such as switch closures, relay coils, LED drivers, and logic-level control lines.

This sample covers the core DT operations you will need in your own application: configuring I/O format (input, low-side output, high-side output, push-pull output), setting output states, managing four voltage threshold levels for logic-level detection, monitoring channel status (BIT, overcurrent, low-to-high and high-to-low transitions), enabling floating-point mode, and configuring the hardware watchdog timer.

This sample supports the following DT module types: K6, K9, KA, KB, DT1, DT4, and DTB. It also works with combination modules that include discrete functionality: CM1, CM2, and CM8. It serves as a practical API reference — each menu command maps directly to one or more naibrd_DT_*() API calls that you can lift into your own code.

Note
For DT interrupt handling, see the DT Interrupts guide.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a DT module installed (K6, K9, KA, KB, DT1, DT4, DTB, CM1, CM2, or CM8).

  • 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 DT_BasicOps executable from your build output directory. On startup the application looks for a configuration file (default_DT_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 DT 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 DT. For details on board connection configuration, see the First Time Setup Guide.

The main() function follows a standard SSK 1.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_DT_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_GetModuleID() so downstream code can adapt to the specific DT variant installed.

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

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_DT_BasicOps(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
                  inputBuffer, &inputResponseCnt);
      }
   }

   naiapp_access_CloseAllOpenCards();
   return 0;
}
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 a DT module. Use the board menu to verify which slots are populated.

Program Structure

Entry Point

On standard platforms the entry point is main(). On VxWorks the entry point is DT_BasicOps() — the SSK 1.x build system selects the correct variant via a preprocessor guard:

#if defined (__VXWORKS__)
int32_t DT_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. Call Run_DT_BasicOps() to validate the module and enter the interactive command loop.

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

Module Detection

Run_DT_BasicOps() calls naibrd_DT_GetChannelCount() with the module ID to determine whether the selected module is a recognized DT type. If the function returns zero channels, the module is not a discrete module and the application reports an error. Otherwise it proceeds to the command loop:

int32_t MaxChannel;

MaxChannel = naibrd_DT_GetChannelCount(ModuleID);

if (MaxChannel == 0)
{
   printf(" *** Module selection not recognized as DT module. ***\n\n");
}
else
{
   Cfg_DT_Channel(cardIndex, module, ModuleID, MaxChannel);
}

Application Parameters

The Cfg_DT_Channel() 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  dt_params;
p_naiapp_AppParameters_t dt_basicops_params = &dt_params;
dt_basicops_params->cardIndex = cardIndex;
dt_basicops_params->module = module;
dt_basicops_params->modId = ModuleID;
dt_basicops_params->channel = chan;
  • cardIndex — identifies which board in a multi-board system.

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

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

  • channel — the currently selected channel (defaults to 1, or 13 for KA modules).

Note
On KA modules, only channels 13-16 are configurable for I/O direction. Channels 1-12 are fixed as outputs and channels 17-28 are fixed as inputs.

Command Loop

Cfg_DT_Channel() 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.

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

Command Description

IO

Set I/O format (input/output mode)

OUT

Set output state (high/low)

Clear

Clear all latched statuses

ML

Set Min Low threshold

L

Set Lower threshold

U

Set Upper threshold

MH

Set Max High threshold

Over

Reset overcurrent

STAT

Display status (BIT, overcurrent, transitions)

Float

Enable/disable floating-point mode

Thres

Set module BIT error threshold

Enable

Enable/disable channel status reporting

Power

Check power-on BIT completed

BIT

Clear module BIT logic

WDT

Open watchdog submenu

Reset

Open module power reset submenu

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

I/O Configuration

This section covers the API calls used to configure discrete channel behavior: setting the I/O format (direction and drive mode) and controlling the output state. Discrete channels are configurable digital lines — when set as outputs, the hardware sources or sinks current through the channel pin at the voltage level determined by the supply rail and threshold settings. When set as inputs, the hardware compares the voltage at the pin against the programmed thresholds to determine the digital state.

Set I/O Format

To configure the I/O direction and drive mode on a channel in your own application, call naibrd_DT_SetIOFormat() with one of the supported format constants.

The available I/O formats are:

  • NAI_DT_IOFORMAT_INPUT — configures the channel as a digital input. The hardware monitors the pin voltage and compares it against the programmed thresholds to determine the logic state.

  • NAI_DT_IOFORMAT_OUTPUT_LOW — configures the channel as a low-side (open-drain) output. The channel sinks current to ground when active.

  • NAI_DT_IOFORMAT_OUTPUT_HIGH — configures the channel as a high-side (open-source) output. The channel sources current from the supply rail when active.

  • NAI_DT_IOFORMAT_OUTPUT_PUSHPULL — configures the channel as a push-pull output. The channel can both source and sink current, driving the pin to either the supply voltage or ground.

uint32_t state = NAI_DT_IOFORMAT_OUTPUT_LOW;

/* Set the channel to low-side output mode */
naibrd_DT_SetIOFormat(cardIndex, module, chan, state);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • chan — the channel to configure.

  • state — one of the four I/O format constants listed above.

Note
On KA and KB modules, only input and low-side output modes are available. High-side and push-pull modes are not supported on these module types. On KA modules, channels 1-12 are fixed as outputs and channels 17-28 are fixed as inputs — only channels 13-16 can be reconfigured.

Set Output State

To set the output level on a channel configured as an output, call naibrd_DT_SetOutputState(). This drives the channel pin high or low according to the configured I/O format. Setting the state on a channel configured as an input has no effect.

nai_dt_state_t outputstate = NAI_DT_STATE_HI;

/* Drive the output pin high */
naibrd_DT_SetOutputState(cardIndex, module, chan, outputstate);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • chan — the channel to set.

  • outputstate — NAI_DT_STATE_HI (1) to drive the output high, or NAI_DT_STATE_LO (0) to drive it low.

To read the current output or input state, use naibrd_DT_GetOutputState() and naibrd_DT_GetInputState() respectively.

Important

Common Errors

  • Output does not toggle — verify that the channel is configured as an output (not input) by checking the I/O format with naibrd_DT_GetIOFormat(). Setting the output state on an input channel has no effect.

  • NAI_ERROR_NOT_SUPPORTED — you attempted to set a high-side or push-pull I/O format on a KA or KB module. These modules only support input and low-side output.

  • KA channel will not change direction — on KA modules, only channels 13-16 support I/O format changes. Channels 1-12 and 17-28 have fixed directions.

Threshold Configuration

Discrete modules use four voltage thresholds to define the boundaries for logic-level detection. These thresholds determine how the hardware interprets the analog voltage at each channel pin as a digital high or low state. The four thresholds form an ordered set of voltage boundaries:

  • Minimum Low (Min Low) — the lowest voltage boundary. If the channel voltage falls below this level, the hardware sets the Min Low status flag. This typically indicates an abnormal under-voltage condition.

  • Lower — the upper boundary of the "logic low" region. A channel voltage below this threshold is considered a definite logic low.

  • Upper — the lower boundary of the "logic high" region. A channel voltage above this threshold is considered a definite logic high.

  • Maximum High (Max High) — the highest voltage boundary. If the channel voltage exceeds this level, the hardware sets the Max High status flag. This typically indicates an abnormal over-voltage condition.

The voltage region between the Lower and Upper thresholds is the "mid-range" zone — a channel voltage in this region is between valid logic states, and the hardware flags this as a mid-range condition.

These four thresholds must maintain the ordering: Min Low < Lower < Upper < Max High. If you set thresholds in an inverted order, the hardware status detection will not function correctly.

Set Min Low Threshold

To set the minimum low voltage threshold on a channel, call naibrd_DT_SetThreshold() with the NAI_DT_THRESH_MIN_LO threshold type:

float64_t threshold = 0.5;

/* Set the Min Low threshold for the channel */
naibrd_DT_SetThreshold(cardIndex, module, chan, NAI_DT_THRESH_MIN_LO, threshold);

Set Lower Threshold

To set the lower voltage threshold (the boundary below which the channel is definitively logic-low), call naibrd_DT_SetThreshold() with NAI_DT_THRESH_LOWER:

float64_t threshold = 2.0;

/* Set the Lower threshold for the channel */
naibrd_DT_SetThreshold(cardIndex, module, chan, NAI_DT_THRESH_LOWER, threshold);

Set Upper Threshold

To set the upper voltage threshold (the boundary above which the channel is definitively logic-high), call naibrd_DT_SetThreshold() with NAI_DT_THRESH_UPPER:

float64_t threshold = 3.5;

/* Set the Upper threshold for the channel */
naibrd_DT_SetThreshold(cardIndex, module, chan, NAI_DT_THRESH_UPPER, threshold);

Set Max High Threshold

To set the maximum high voltage threshold on a channel, call naibrd_DT_SetThreshold() with NAI_DT_THRESH_MAX_HI:

float64_t threshold = 5.5;

/* Set the Max High threshold for the channel */
naibrd_DT_SetThreshold(cardIndex, module, chan, NAI_DT_THRESH_MAX_HI, threshold);

Threshold API Parameters

All four threshold functions share the same API signature:

  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • chan — the channel to configure.

  • thresholdtype — one of NAI_DT_THRESH_MIN_LO, NAI_DT_THRESH_LOWER, NAI_DT_THRESH_UPPER, or NAI_DT_THRESH_MAX_HI.

  • threshold — the voltage level as a float64_t. Consult your module’s manual for the valid voltage range.

To read the current threshold setting, use naibrd_DT_GetThreshold() with the same threshold type constants.

Important

Common Errors

  • Thresholds set in wrong order — the four thresholds must satisfy Min Low < Lower < Upper < Max High. If you accidentally set the Upper threshold below the Lower threshold (or any other inversion), the hardware status flags will not trigger correctly. Always verify the ordering after configuration.

  • Mid-range status always set — if the Lower and Upper thresholds are set too close together or at the same value, the channel will frequently report mid-range status. Ensure adequate separation between the Lower and Upper thresholds for your signal levels.

  • Status flags not reflecting expected voltage — verify that your threshold values match the actual signal voltage range. Consult your module’s manual for the valid threshold range for your specific module type.

Status and Diagnostics

This section covers the API calls used to read channel status, manage latched status flags, configure BIT (Built-In Test) error detection, and enable per-channel status reporting. The discrete module hardware continuously monitors each channel and sets status flags when threshold crossings, overcurrent conditions, or BIT failures are detected.

Display Status

To read the status of a channel, call naibrd_DT_GetStatus() with the desired status type. The sample reads and displays the following latched status flags for the selected channel:

  • Min Low (NAI_DT_STATUS_MIN_LO_LATCHED) — channel voltage dropped below the Min Low threshold.

  • Mid-Range (NAI_DT_STATUS_MID_RANGE_LATCHED) — channel voltage is between the Lower and Upper thresholds (indeterminate logic state).

  • Max High (NAI_DT_STATUS_MAX_HI_LATCHED) — channel voltage exceeded the Max High threshold.

  • Low-to-High Transition (NAI_DT_STATUS_LO_HI_TRANS_LATCHED) — a rising-edge transition was detected (channel went from below Lower to above Upper).

  • High-to-Low Transition (NAI_DT_STATUS_HI_LO_TRANS_LATCHED) — a falling-edge transition was detected (channel went from above Upper to below Lower).

  • BIT (NAI_DT_STATUS_BIT_LATCHED) — the Built-In Test detected a fault on this channel.

  • Overcurrent (NAI_DT_STATUS_OVERCURRENT_LATCHED) — the channel drew more current than the hardware limit allows.

On DT1, DT4, DTB, CM1, and CM2 modules, the following additional status flags are available:

  • Summary (NAI_DT_STATUS_SUMMARY_LATCHED) — a summary flag indicating that any status condition has been detected.

  • Watchdog Timer Fault (NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED) — the watchdog timer expired without being strobed.

  • Inter-FPGA CRC Fault (NAI_DT_STATUS_CRC_FAULT_LATCHED) — a CRC error was detected on the inter-FPGA communication link.

nai_status_bit_t status;

/* Read the latched BIT status for a channel */
naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED, &status);

/* Read the latched overcurrent status */
naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, &status);

/* Read a low-to-high transition */
naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, &status);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • chan — the channel to query.

  • The fourth parameter selects the status type.

  • status — receives the status value (0 = not set, 1 = set).

Real-time (non-latched) variants of each status type are also available (e.g., NAI_DT_STATUS_BIT for real-time BIT). Latched status remains set until explicitly cleared; real-time status reflects the current hardware state.

Clear All Statuses

To clear all latched status flags for a channel, the sample reads each latched status and clears it if it is set. In your own application, you would follow the same pattern — check each status type and call naibrd_DT_ClearStatus() for any that are active:

nai_status_bit_t status = 0u;

/* Check and clear the latched BIT status */
naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED, &status);
if (status == 1u)
{
   naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED);
}

/* Check and clear the latched overcurrent status */
naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, &status);
if (status == 1u)
{
   naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED);
}

The sample clears all of the following latched statuses: BIT, overcurrent, Max High, Min Low, mid-range, low-to-high transition, and high-to-low transition. On DT1/DT4/DTB/CM1/CM2 modules it also clears watchdog timer fault, CRC fault, and summary statuses.

Reset Overcurrent

To reset the overcurrent condition on all channels, call naibrd_DT_ResetAll() with the NAI_DT_RESET_OVERCURRENT reset type. To reset overcurrent on a single channel (Gen 5 modules only), call naibrd_DT_Reset():

/* Reset overcurrent on all channels */
naibrd_DT_ResetAll(cardIndex, module, NAI_DT_RESET_OVERCURRENT);

/* Reset overcurrent on channel 1 only (Gen 5 modules) */
naibrd_DT_Reset(cardIndex, module, 1, NAI_DT_RESET_OVERCURRENT);

An overcurrent condition means the channel attempted to source or sink more current than the hardware protection limit allows. This can occur if the external load impedance is too low or if there is a wiring fault. After resolving the external cause, call the reset function to clear the condition and restore normal operation.

Channel Status Enable

To enable or disable per-channel status reporting, call naibrd_DT_SetChanStatusEnable(). When status reporting is disabled for a channel, the hardware does not update the status flags for that channel. This feature is available on DT1, DT4, DTB, CM1, and CM2 modules only.

bool_t chanStatusEnable = TRUE;

/* Enable status reporting for the channel */
naibrd_DT_SetChanStatusEnable(cardIndex, module, chan, chanStatusEnable);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • chan — the channel to configure.

  • chanStatusEnable — TRUE to enable status reporting, FALSE to disable it.

BIT Error Threshold

To set the module-level BIT error threshold, call naibrd_DT_SetModuleBITErrorThreshold(). The BIT error threshold controls how many consecutive BIT test failures must occur before the hardware sets the BIT status flag. A higher threshold makes BIT reporting less sensitive to transient faults. This feature is available on DT1, DT4, DTB, CM1, and CM2 modules only.

uint32_t bitErrThres = 5;

/* Set the BIT error threshold for the module */
naibrd_DT_SetModuleBITErrorThreshold(cardIndex, module, bitErrThres);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • bitErrThres — the number of consecutive BIT failures before the status flag is set. Must be a non-negative integer.

Check Power-On BIT Complete

To check whether the module has completed its power-on Built-In Test, call naibrd_DT_CheckPowerOnBITComplete(). After power-on BIT completes, you can read the BIT status of each channel to determine whether any channels failed the test. This feature is available on DT1, DT4, DTB, CM1, and CM2 modules only.

bool_t pBitComplete = FALSE;

/* Check if power-on BIT has completed */
naibrd_DT_CheckPowerOnBITComplete(cardIndex, module, &pBitComplete);

if (pBitComplete)
{
   /* Read the BIT status for each channel */
   nai_status_bit_t bitStatus;
   int32_t channelCount = naibrd_DT_GetChannelCount(ModuleID);
   for (int32_t ch = 1; ch <= channelCount; ch++)
   {
      naibrd_DT_GetStatus(cardIndex, module, ch, NAI_DT_STATUS_BIT_LATCHED, &bitStatus);
      /* bitStatus == 0: passed, bitStatus == 1: FAILED */
   }
}

Clear Module BIT Logic

To reset the Continuous BIT internal circuitry and error counter, call naibrd_DT_ClearModuleBITLogic(). This clears the BIT state machine and resets the failure counter to zero, allowing BIT testing to start fresh. This is useful after resolving a known hardware condition that was causing BIT failures. This feature is available on DT1, DT4, DTB, CM1, and CM2 modules only.

/* Reset the Continuous BIT circuitry and counter */
naibrd_DT_ClearModuleBITLogic(cardIndex, module, chan);

Floating-Point Mode Enable

To enable or disable hardware floating-point conversion mode for the entire module, call naibrd_SetFloatingPointModeEnable(). When enabled, the module returns threshold and voltage readings as IEEE 754 floating-point values rather than raw register values. This is a module-wide setting that affects all channels.

bool_t floatModeEnable = TRUE;

/* Enable floating-point mode for the module */
naibrd_SetFloatingPointModeEnable(cardIndex, module, floatModeEnable);
  • cardIndex — identifies the board.

  • module — the slot containing the DT module.

  • floatModeEnable — TRUE to enable floating-point mode, FALSE to disable it.

To read the current floating-point mode state, use naibrd_GetFloatingPointModeEnable().

Important

Common Errors

  • Status flags never set — channel status reporting may be disabled. Call naibrd_DT_SetChanStatusEnable() with TRUE to enable it. This feature is only available on DT1/DT4/DTB/CM1/CM2 modules.

  • BIT failures after power-on — verify that power-on BIT has completed before reading BIT status. Call naibrd_DT_CheckPowerOnBITComplete() first.

  • Overcurrent persists after clearing — the external fault condition (low impedance load, wiring short) must be resolved before the overcurrent reset will take effect. The hardware will immediately re-trigger the overcurrent flag if the fault is still present.

  • Floating-point mode has no effect — verify that the module supports floating-point mode. Not all legacy modules support this feature.

Watchdog and Power Reset

Watchdog Timer

The discrete module includes a hardware watchdog timer that provides a safety mechanism for output channels. When the watchdog is active, your application must periodically "strobe" (pet) the watchdog within a defined time window. If your application fails to strobe the watchdog in time — for example, due to a software crash, communication loss, or host processor fault — the hardware automatically shuts off all outputs on the module. This prevents discrete output channels from being stuck in an uncontrolled state when the controlling software is no longer functioning.

The watchdog timing is defined by two parameters:

  • Quiet Time — after each strobe, the watchdog ignores additional strobes for this duration. This prevents accidental double-strobes from resetting the timer too early. Recommended minimum: 500 ms for this sample application.

  • Window Time — after the quiet time expires, the watchdog opens a window during which it expects the next strobe. If the window closes without receiving a strobe, the watchdog triggers a fault and shuts off all outputs. Recommended minimum: 500 ms for this sample application.

The strobe timing in your application should be: wait for (Quiet Time) + (Window Time / 2), then strobe. This places the strobe in the middle of the window for maximum timing margin.

The watchdog submenu provides the following commands:

Command Description

TIME QUIET

Set the watchdog quiet time (in milliseconds)

WINDOW

Set the watchdog window time (in milliseconds)

STROBE

Start a background thread that continuously strobes the watchdog

KILL

Stop the watchdog strobing thread

BACK

Return to the main menu

Set Watchdog Quiet Time

To set the watchdog quiet time, call naibrd_DT_SetWatchdogQuietTime(). The API accepts the value in microseconds, so the sample multiplies the user’s millisecond input by 1000:

uint32_t quietTime = 500; /* milliseconds */

/* Set the watchdog quiet time (API takes microseconds) */
naibrd_DT_SetWatchdogQuietTime(cardIndex, module, quietTime * 1000);

Set Watchdog Window Time

To set the watchdog window time, call naibrd_DT_SetWatchdogWindow(). Like the quiet time, the API accepts microseconds:

uint32_t windowTime = 500; /* milliseconds */

/* Set the watchdog window time (API takes microseconds) */
naibrd_DT_SetWatchdogWindow(cardIndex, module, windowTime * 1000);

Strobe the Watchdog

To strobe (pet) the watchdog, call naibrd_DT_WatchdogStrobe(). The sample spawns a background thread that continuously strobes the watchdog at the interval (Quiet Time) + (Window Time / 2):

/* Read current timing parameters */
naibrd_DT_GetWatchdogQuietTime(cardIndex, module, &quietTime);
naibrd_DT_GetWatchdogWindow(cardIndex, module, &windowTime);
quietTime = quietTime / 1000;   /* convert to ms */
windowTime = windowTime / 1000; /* convert to ms */
delayTime = quietTime + (windowTime / 2);

/* Strobe the watchdog */
naibrd_DT_WatchdogStrobe(cardIndex, module);

/* In a loop, delay then strobe again */
do
{
   nai_msDelay(delayTime);
   naibrd_DT_WatchdogStrobe(cardIndex, module);
} while (!terminateThread);
Warning
When the watchdog strobing thread is killed or the application exits while the watchdog is active, the module will shut off all outputs. The module will need to be power-cycled to restore normal operation.

Display Watchdog Status

The watchdog submenu displays the current quiet time, window time, and watchdog fault status (both real-time and latched) each time it refreshes:

nai_status_bit_t wdStatLatched = 0u;
nai_status_bit_t wdStatRT = 0u;

naibrd_DT_GetWatchdogQuietTime(cardIndex, module, &quietTime);
naibrd_DT_GetWatchdogWindow(cardIndex, module, &windowTime);
naibrd_DT_GetStatus(cardIndex, module, chan,
   NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED, &wdStatLatched);
naibrd_DT_GetStatus(cardIndex, module, chan,
   NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_REALTIME, &wdStatRT);
Note
The watchdog timer feature is available on DT1, DT4, DTB, CM1, and CM2 modules only. On other module types, selecting the watchdog menu displays "Module does not support Watchdog Timer!"

Module Power Reset

The module power reset submenu allows you to view module power status flags and issue power control requests. This is available on DT1, DT4, DTB, CM1, and CM2 modules only.

The power reset status flags include:

  • Powered Down — the module is currently powered down.

  • Not Detected — the module was not detected by the board.

  • Not Link Init — the inter-FPGA communication link has not initialized.

  • Comm Error — a communication error has occurred.

The power reset request types are:

  • Reset (NAI_DT_MODULE_POWER_RESET_REQUEST_RESET) — request a module reset.

  • Power Down (NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_DOWN) — request the module to power down.

  • Power Up (NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_UP) — request the module to power up.

/* Read a power reset status flag */
bool_t poweredDownStatus;
naibrd_DT_GetModulePowerResetStatus(cardIndex, module,
   NAI_DT_MODULE_POWER_RESET_STATUS_POWERED_DOWN, &poweredDownStatus);

/* Issue a reset request */
naibrd_DT_SetModulePowerReset(cardIndex, module,
   NAI_DT_MODULE_POWER_RESET_REQUEST_RESET, (bool_t)TRUE);

/* Clear a power reset status flag */
naibrd_DT_ClearModulePowerResetStatus(cardIndex, module,
   NAI_DT_MODULE_POWER_RESET_STATUS_POWERED_DOWN);
Important

Common Errors

  • Watchdog timeout shuts off outputs unexpectedly — ensure your strobe interval is within the window. The strobe must arrive after the quiet time has elapsed but before the window time expires. Use (Quiet Time) + (Window Time / 2) as your strobe interval.

  • Outputs do not recover after watchdog fault — after a watchdog timeout, the module shuts off all outputs and requires a power cycle to restore operation. This is a safety feature by design.

  • Module power reset commands not available — this feature is only supported on DT1, DT4, DTB, CM1, and CM2 modules.

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_DT_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.

Wrong I/O format selected

Channel set as input when output was intended, or vice versa

Call naibrd_DT_GetIOFormat() to verify the current format, then call naibrd_DT_SetIOFormat() with the correct constant. On KA modules, remember that channels 1-12 and 17-28 have fixed directions.

Thresholds misconfigured (inverted order)

Min Low, Lower, Upper, and Max High thresholds not in ascending order

Verify that Min Low < Lower < Upper < Max High. Read back all four thresholds with naibrd_DT_GetThreshold() and correct any inversions.

Overcurrent condition persists

External load impedance too low, wiring fault, or short circuit on the output channel

Resolve the external fault first, then call naibrd_DT_ResetAll() or naibrd_DT_Reset() with NAI_DT_RESET_OVERCURRENT. The hardware will re-trigger the overcurrent flag if the fault is still present.

BIT failure on one or more channels

Open input, hardware fault, or channel not connected

Check input wiring. Verify that power-on BIT has completed with naibrd_DT_CheckPowerOnBITComplete(). Consult your module’s manual for diagnostic procedures.

Watchdog timeout shuts off outputs

Strobe interval too long, application crash, communication loss

Ensure your strobe arrives within the watchdog window. Use (Quiet Time) + (Window Time / 2) as the strobe interval. After a watchdog fault, the module requires a power cycle to restore outputs.

Output not toggling when state is set

Channel configured as input, or overcurrent condition has shut off the output driver

Verify I/O format is set to an output mode. Check and clear any overcurrent conditions.

Floating-point mode readings differ from expected

Mode not enabled, or mode enabled on a module that does not support it

Call naibrd_GetFloatingPointModeEnable() to verify the mode is active. Not all legacy modules support floating-point mode.

NAI_ERROR_NOT_SUPPORTED

Feature not available for this module type (e.g., watchdog on K6, channel status enable on K9)

Check your module type. Features such as watchdog, BIT threshold, channel status enable, and module power reset are only available on DT1, DT4, DTB, CM1, and CM2 modules.

Full Source

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

Full Source — DT_BasicOps.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#if defined (LINUX)
#include <pthread.h>
#endif

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

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_dt.h"
#include "advanced/nai_ether_adv.h"

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

/* Function prototypes */
int32_t Run_DT_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID);
static void Cfg_DT_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);

static void Display_DT_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
static nai_status_t Display_DT_Status(int32_t paramCount, int32_t* p_params);

static nai_status_t Configure_DT_IOFormat(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_OutputState(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_ChanStatusEnable(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_FloatingPointEnable(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_ClearAllStatuses(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_MinLoThreshold(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_LowThreshold(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_UpperThreshold(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_MaxHiThreshold(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_Threshold(int32_t cardIndex, int32_t module, int32_t chan, nai_dt_thresh_type_t thresholdtype, int8_t* thresholdtext);
static nai_status_t Configure_DT_BITErrorThreshold(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_CheckPBITComplete(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_DT_ClearModuleBITLogic(int32_t paramCount, int32_t* p_params);
static bool_t configurable_DT_IOFormat(uint32_t ModuleID, int32_t chan);
static bool_t configurable_DT_Output(uint32_t ModuleID, int32_t chan);

static nai_status_t Handle_DT_WatchdogShowMenu(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_DT_WatchDogQuietTime(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_DT_WatchDogWindowTime(int32_t paramCount, int32_t* p_params);
static bool_t Handle_DT_DisplayWatchdog(int32_t cardIndex, int32_t module, int32_t chan);
static nai_status_t Handle_DT_StrobeWatchdog(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_DT_kill_WDStrobe_Thread(int32_t paramCount, int32_t* p_params);
static void naiapp_kill_WDStrobe_Thread();

static nai_status_t Handle_DT_ModulePowerResetMenu(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_DT_ClearModulePowerResetStatus(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_DT_SetModulePowerReset(int32_t paramCount, int32_t* p_params);

static const int32_t DEF_DT_CHANNEL       = 1;
static const int32_t DEF_DT_KA_CHANNEL    = 13;
static const int8_t *SAMPLE_WD_PGM_NAME = (const int8_t*)"DT Watchdog Operations";
static const int8_t *SAMPLE_MODULE_POWER_RESET_PGM_NAME = (const int8_t*)"DT Module Power Reset Menu";
static bool_t terminateThread;

#if defined (WIN32)
DWORD WINAPI WD_Strobe_ThreadEntryPoint(LPVOID param);
#elif defined (LINUX)
void* WD_Strobe_ThreadEntryPoint(void* arg);
#elif defined (__VXWORKS__)
static int WD_Strobe_ThreadEntryPoint(int32_t nParam);
#else
#error Unsupported OS
#endif
/* TX Thread */
#if defined (WIN32)
static HANDLE thread = NULL;
#elif defined (LINUX)
static pthread_t thread;
#elif defined (__VXWORKS__)
static int thread;
#else
#error Unsupported OS
#endif

/****** Command Table *******/
enum dt_basicops_commands
{
   DT_BASICOP_CMD_IOFORMAT,
   DT_BASICOP_CMD_OUTPUTSTATE,
   DT_BASICOP_CMD_CLEAR_ALL_STATUSES,
   DT_BASICOP_CMD_THRESHOLD_MIN_LO,
   DT_BASICOP_CMD_THRESHOLD_LOWER,
   DT_BASICOP_CMD_THRESHOLD_UPPER,
   DT_BASICOP_CMD_THRESHOLD_MAX_HI,
   DT_BASICOP_CMD_RESET_OC,
   DT_BASICOP_CMD_STATUS,
   DT_BASICOP_CMD_FLOATING_POINT_MODE_ENABLE,
   DT_BASICOP_CMD_SET_BIT_ERROR_THRESHOLD,
   DT_BASICOP_CMD_CHAN_STATUS_ENABLE,
   DT_BASICOP_CMD_CHECK_POWER_ON_BIT_COMPLETE,
   DT_BASICOP_CMD_CLEAR_MODULE_BIT_LOGIC,
   DT_BASICOP_CMD_WATCHDOG_MENU,
   DT_BASICOP_CMD_MODULE_POWER_RESET,
   DT_BASICOP_CMD_COUNT
};

enum dt_watchdog_commands
{
   DT_WD_CMD_QUIETTIME,
   DT_WD_CMD_WINDOWTIME,
   DT_WD_CMD_STROBE,
   DT_WD_CMD_KILL,
   DT_WD_CMD_BACK,
   DT_WD_CMD_COUNT
};

enum dt_module_power_reset_commands
{
   DT_MODULE_POWER_RESET_CMD_BACK,
   DT_MODULE_POWER_RESET_CMD_CLEAR_MODULE_POWER_RESET_STATUS,
   DT_MODULE_POWER_RESET_CMD_SET_MODULE_POWER_RESET,
   DT_MODULE_POWER_RESET_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t DT_BasicOpMenuCmds[] = {
   {"IO",     "DT Set IO Format",                           DT_BASICOP_CMD_IOFORMAT,                    Configure_DT_IOFormat},
   {"OUT",    "DT Set Output State",                        DT_BASICOP_CMD_OUTPUTSTATE,                 Configure_DT_OutputState},
   {"Clear",  "DT Clear All Latched Statuses",              DT_BASICOP_CMD_CLEAR_ALL_STATUSES,          Configure_DT_ClearAllStatuses},
   {"ML",     "DT Set Min Low Threshold",                   DT_BASICOP_CMD_THRESHOLD_MIN_LO,            Configure_DT_MinLoThreshold},
   {"L",      "DT Set Lower Threshold",                     DT_BASICOP_CMD_THRESHOLD_LOWER,             Configure_DT_LowThreshold},
   {"U",      "DT Set Upper Threshold",                     DT_BASICOP_CMD_THRESHOLD_UPPER,             Configure_DT_UpperThreshold},
   {"MH",     "DT Set Max High Threshold",                  DT_BASICOP_CMD_THRESHOLD_MAX_HI,            Configure_DT_MaxHiThreshold},
   {"Over",   "DT Reset Overcurrent",                       DT_BASICOP_CMD_RESET_OC,                    NULL},
   {"STAT",   "DT Display Status",                          DT_BASICOP_CMD_STATUS,                      Display_DT_Status},
   {"Float",  "DT Enable/Disable Floating-Point Mode",      DT_BASICOP_CMD_FLOATING_POINT_MODE_ENABLE,  Configure_DT_FloatingPointEnable},
   {"Thres",  "DT Set Module BIT Error Threshold",          DT_BASICOP_CMD_SET_BIT_ERROR_THRESHOLD,     Configure_DT_BITErrorThreshold},
   {"Enable", "DT Enable/Disable Channel Status Reporting", DT_BASICOP_CMD_CHAN_STATUS_ENABLE,          Configure_DT_ChanStatusEnable},
   {"Power",  "DT Check Power-On BIT Completed",            DT_BASICOP_CMD_CHECK_POWER_ON_BIT_COMPLETE, Configure_DT_CheckPBITComplete},
   {"BIT",    "DT Clear Module BIT Logic",                  DT_BASICOP_CMD_CLEAR_MODULE_BIT_LOGIC,      Configure_DT_ClearModuleBITLogic},
   {"WDT",    "Show Watchdog Menu Options",                 DT_BASICOP_CMD_WATCHDOG_MENU,               Handle_DT_WatchdogShowMenu},
   {"Reset",  "Show Module Power Reset Menu Options",       DT_BASICOP_CMD_MODULE_POWER_RESET,          Handle_DT_ModulePowerResetMenu}
};

naiapp_cmdtbl_params_t DT_WatchdogOpMenuCmds[DT_WD_CMD_COUNT] =
{
   {"BACK",           "Back to Main Menu",                             DT_WD_CMD_BACK,          NULL},
   {"TIME QUIET",     "Set Watchdog Quiet Time",                       DT_WD_CMD_QUIETTIME,     Handle_DT_WatchDogQuietTime},
   {"WINDOW",         "Set Watchdog Window Time",                      DT_WD_CMD_WINDOWTIME,    Handle_DT_WatchDogWindowTime},
   {"STROBE",         "Start thread to continuously strobe watchdog",  DT_WD_CMD_STROBE,        Handle_DT_StrobeWatchdog},
   {"KILL",           "Kill Watchdog strobing thread",                 DT_WD_CMD_KILL,           Handle_DT_kill_WDStrobe_Thread}
};

naiapp_cmdtbl_params_t DT_ModulePowerResetMenuCmds[DT_MODULE_POWER_RESET_CMD_COUNT] =
{
   {"BACK",  "Back to Main Menu",               DT_MODULE_POWER_RESET_CMD_BACK,                            NULL},
   {"CLEAR", "Clear Module Power Reset Status", DT_MODULE_POWER_RESET_CMD_CLEAR_MODULE_POWER_RESET_STATUS, Handle_DT_ClearModulePowerResetStatus},
   {"SET",   "Set Module Power Reset Request",  DT_MODULE_POWER_RESET_CMD_SET_MODULE_POWER_RESET,          Handle_DT_SetModulePowerReset}
};

/**************************************************************************************************************/
/**
<summary>
The purpose of the DT_BasicOps is to illustrate the methods to call in the naibrd library to perform basic
 operations with the discrete modules for configuration setup, controlling the drive outputs, 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 DT routines.
 - ClearDeviceCfg
 - QuerySystemCfg
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DT_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_DT_BasicOps(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
<summary>
Run_DT_BasicOps prompts the user for the card, module and channel to use for the application and calls
Cfg_DT_Channel if the card, module, channel is valid for as a discrete module.
</summary>
*/
/**************************************************************************************************************/
int32_t Run_DT_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
   int32_t MaxChannel;

   MaxChannel = naibrd_DT_GetChannelCount(ModuleID);

   if (MaxChannel == 0)
   {
      printf(" *** Module selection not recognized as DT module. ***\n\n");
   }
   else
   {
      Cfg_DT_Channel(cardIndex, module, ModuleID, MaxChannel);
   }
   return cardIndex;
}

/**************************************************************************************************************/
/**
<summary>
Cfg_DT_Channel handles calling the Display_DT_ChannelCfg routine to display the discrete channel configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
static void Cfg_DT_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   int32_t chan, defaultchan = 1;
   nai_status_t status = (nai_status_t)0;
   int32_t cmd;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiapp_AppParameters_t  dt_params;
   p_naiapp_AppParameters_t dt_basicops_params = &dt_params;
   dt_basicops_params->cardIndex = cardIndex;
   dt_basicops_params->module = module;
   dt_basicops_params->modId = ModuleID;

   while (bContinue)
   {
      printf("    \r\n\r\n");
      printf("Channel selection \r\n");
      printf("================= \r\n");
      if (ModuleID == NAI_MODULE_ID_KA)
      {
         printf("\n For KA modules, only Channels 13-16 are configurable.");
         printf("\n Ch.01-12 are output only, Ch.17-28 are input only. \n");
         defaultchan = DEF_DT_KA_CHANNEL;
      }
      else
         defaultchan = DEF_DT_CHANNEL;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);
      dt_basicops_params->channel = chan;

      naiapp_utils_LoadParamMenuCommands(DT_BASICOP_CMD_COUNT, DT_BasicOpMenuCmds);
      while (bContinue)
      {
         Display_DT_ChannelCfg(cardIndex, module, chan, ModuleID);
         naiapp_display_ParamMenuCommands((int8_t *)"DT Basic Operation Menu");
         printf("\nType DT command or %c to quit : main >", NAI_QUIT_CHAR);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
               if (bCmdFound)
               {
                  switch (cmd)
                  {
                  case DT_BASICOP_CMD_IOFORMAT:
                  case DT_BASICOP_CMD_OUTPUTSTATE:
                  case DT_BASICOP_CMD_CLEAR_ALL_STATUSES:
                  case DT_BASICOP_CMD_THRESHOLD_MIN_LO:
                  case DT_BASICOP_CMD_THRESHOLD_LOWER:
                  case DT_BASICOP_CMD_THRESHOLD_UPPER:
                  case DT_BASICOP_CMD_THRESHOLD_MAX_HI:
                  case DT_BASICOP_CMD_STATUS:
                  case DT_BASICOP_CMD_FLOATING_POINT_MODE_ENABLE:
                  case DT_BASICOP_CMD_SET_BIT_ERROR_THRESHOLD:
                  case DT_BASICOP_CMD_CHAN_STATUS_ENABLE:
                  case DT_BASICOP_CMD_CHECK_POWER_ON_BIT_COMPLETE:
                  case DT_BASICOP_CMD_CLEAR_MODULE_BIT_LOGIC:
                  case DT_BASICOP_CMD_WATCHDOG_MENU:
                  case DT_BASICOP_CMD_MODULE_POWER_RESET:
                     DT_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)dt_basicops_params);
                     break;
                  case DT_BASICOP_CMD_RESET_OC:
                     status = check_status(naibrd_DT_ResetAll(cardIndex, module, NAI_DT_RESET_OVERCURRENT));   /*This resets all channels*/
                     status = check_status(naibrd_DT_Reset(cardIndex, module, 1, NAI_DT_RESET_OVERCURRENT));  /*This alternate function resets channel 1 only on Gen5 modules. */
                     if (status == NAI_SUCCESS)
                        printf("Reset completed. \n\n");
                     break;
                  default:
                     printf("Invalid command entered\n");
                     break;
                  }
               }
               else
                  printf("Invalid command entered\n");
            }
         }
         else
            bContinue = FALSE;
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
Display_DT_ChannelCfg illustrate the methods to call in the naibrd library to retrieve the configuration states
for basic operation.
</summary>
*/
/**************************************************************************************************************/
static void Display_DT_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
   bool_t chanStatusEnabled = FALSE;
   bool_t floatModeEnabled = FALSE;
   bool_t pBITComplete = FALSE;
   uint32_t bitErrThres = 0u;
   uint32_t ioformat = 0;
   nai_dt_state_t outputstate = 0;
   nai_dt_state_t inputstate = 0;
   float64_t minlo= 0.0, lower = 0.0, upper = 0.0, maxhi = 0.0, voltage = 0.0, vcc = 0.0, current = 0.0;
   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   int32_t MaxChannel;
   uint32_t bank;
   char strChanStatusEnabled[10] = "";
   char strFloatModeEnabled[10] = "";
   char strPBITComplete[14] = "";
   naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
   if ((ModuleID == NAI_MODULE_ID_KA) && ((chan < 13) || (chan > 16)) )
   {
      if (chan < 13) /*KA Ch. 1-12 fixed as output channels*/
         ioformat = NAI_DT_IOFORMAT_OUTPUT_LOW;
      else           /*KA Ch. 17-28 fixed as input channels*/
         ioformat = NAI_DT_IOFORMAT_INPUT;
   }
   else
   {
      check_status(naibrd_DT_GetIOFormat(cardIndex, module, chan, &ioformat));
   }

   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      check_status(naibrd_DT_GetChanStatusEnable(cardIndex, module, chan, &chanStatusEnabled));
      switch (chanStatusEnabled)
      {
         case (bool_t)TRUE:
            sprintf(strChanStatusEnabled, "Enabled ");
         break;
         case (bool_t)FALSE:
            sprintf(strChanStatusEnabled, "Disabled");
         break;
         default:
            sprintf(strChanStatusEnabled, "Unknown ");
         break;
      }
      check_status(naibrd_GetFloatingPointModeEnable(cardIndex, module, &floatModeEnabled));
      switch (floatModeEnabled)
      {
         case (bool_t)TRUE:
            sprintf(strFloatModeEnabled, "Enabled ");
         break;
         case (bool_t)FALSE:
            sprintf(strFloatModeEnabled, "Disabled");
         break;
         default:
            sprintf(strFloatModeEnabled, "Unknown ");
         break;
      }
      check_status(naibrd_DT_CheckPowerOnBITComplete(cardIndex, module, &pBITComplete));
      switch (pBITComplete)
      {
         case (bool_t)TRUE:
            sprintf(strPBITComplete, "Completed    ");
         break;
         case (bool_t)FALSE:
            sprintf(strPBITComplete, "Not Completed");
         break;
         default:
            sprintf(strPBITComplete, "Unknown      ");
         break;
      }
      check_status(naibrd_DT_GetModuleBITErrorThreshold(cardIndex, module, &bitErrThres));
   }
   check_status(naibrd_DT_GetOutputState(cardIndex, module, chan, &outputstate));
   check_status(naibrd_DT_GetInputState(cardIndex, module, chan, &inputstate));
   check_status(naibrd_DT_GetThreshold(cardIndex, module, chan, NAI_DT_THRESH_MIN_LO, &minlo));
   check_status(naibrd_DT_GetThreshold(cardIndex, module, chan, NAI_DT_THRESH_LOWER, &lower));
   check_status(naibrd_DT_GetThreshold(cardIndex, module, chan, NAI_DT_THRESH_UPPER, &upper));
   check_status(naibrd_DT_GetThreshold(cardIndex, module, chan, NAI_DT_THRESH_MAX_HI, &maxhi));

   /* Get the number of VCC banks for the module */
   bank = naibrd_DT_GetVCCBankCount(ModuleID);
   MaxChannel = naibrd_DT_GetChannelCount(ModuleID);

   if (ModuleID != NAI_MODULE_ID_KA)
   {
      /*read channel voltage and Vcc*/
      check_status(naibrd_DT_GetVoltage(cardIndex, module, chan, &voltage));
   }
   if ((ModuleID == NAI_MODULE_ID_K6) || (ModuleID == NAI_MODULE_ID_K9) || (ModuleID == NAI_MODULE_ID_DT1) ||
       (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      check_status(naibrd_DT_GetBankVccVoltage(cardIndex, module, ((chan-1)/(MaxChannel/bank)+1), &vcc));
      /*read current*/
      check_status(naibrd_DT_GetCurrent(cardIndex, module, chan, &current));
   }

   printf("\n === Channel %d ===\n\n", chan);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf("           Floating-Point Mode (all channels): %s\n", strFloatModeEnabled);
      printf(" Module Power-On BIT Completed (all channels): %s\n", strPBITComplete);
      printf("    Module BIT Error Threshold (all channels): %u\n", bitErrThres);
      printf("                        Channel Status Enable: %s\n\n", strChanStatusEnabled);
   }
   /*Channel voltage readings available for the following modules :  K6 V4 and up, K9, KB, PD+ (not on KA) */
   /*Channel current readings not applicable for the following modules:       KA, KB, PD              */
   /*Vcc readings not applicable for the following modules:                   KA, KB, PD              */

   if (ModuleID == NAI_MODULE_ID_KA || ModuleID == NAI_MODULE_ID_KB)
   {
      printf(" IOFormat  Output Input  MinLow   Lower    Upper     Max Hi\n");
      printf(" --------- ------ ----- -------  -------  -------   --------\n");
   }
   else if (((ModuleID == NAI_MODULE_ID_K6) && (ModuleVer >= 4)) || (ModuleID == NAI_MODULE_ID_K9) || (ModuleID == NAI_MODULE_ID_DT1) ||
            (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf(" IOFormat  Output Input  MinLow   Lower     Upper    Max Hi  Voltage \n");
      printf(" --------- ------ ----- -------  -------  --------  -------- ------- \n");
   }

   switch (ioformat)
   {
   case NAI_DT_IOFORMAT_INPUT:
      printf("  Input   ");
      break;
   case NAI_DT_IOFORMAT_OUTPUT_LOW:
      printf(" Low-side ");
      break;
   case NAI_DT_IOFORMAT_OUTPUT_HIGH:
      printf(" High-side");
      break;
   case NAI_DT_IOFORMAT_OUTPUT_PUSHPULL:
      printf(" Push-pull");
      break;
   default:
      printf(" Unknown  ");
      break;
   }

   if (ioformat != NAI_DT_IOFORMAT_INPUT)
   {
      switch (outputstate)
      {
      case NAI_DT_STATE_LO:
         printf("  Low ");
         break;
      case NAI_DT_STATE_HI:
         printf("  High");
         break;
      /* undefined value read back */
      default:
         printf("  UNK ");
         break;
      }
   }
   else
      printf("  --- ");

   printf("  %3i   ", inputstate);
   printf("%+6.1f   %+6.1f   %+6.1f    %+6.1f   ", minlo, lower, upper, maxhi);

   if (ModuleID != NAI_MODULE_ID_KA)
   {
      printf("%+6.1f    ", voltage);
   }

  if (((ModuleID == NAI_MODULE_ID_K6) && (ModuleVer >= 4)) || (ModuleID == NAI_MODULE_ID_K9) || (ModuleID == NAI_MODULE_ID_DT1) ||
      (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
     printf("\n\n");
      printf("\n  VCC     Current (mA)\n");
      printf("\n ------   ------------\n");

      printf("%+6.1f    ", vcc);
      printf("%+6.1f    ", current*1000); /*display in mA*/
   }
}

/**************************************************************************************************************/
/**
<summary>
Display_DT_Status illustrate the methods to call in the naibrd library to retrieve the status states.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Display_DT_Status(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
   nai_status_bit_t status;
   uint32_t ModuleID;

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

   /* Available status:
         NAI_DT_STATUS_BIT,
         NAI_DT_STATUS_OVER_CURRENT,
         NAI_DT_STATUS_MAX_HI,
         NAI_DT_STATUS_MIN_LO,
         NAI_DT_STATUS_MID_RANGE,
         NAI_DT_STATUS_LO_HI_TRANS,
         NAI_DT_STATUS_HI_LO_TRANS,
         NAI_DT_STATUS_SUMMARY,
         NAI_DT_STATUS_WATCHDOG_TIMER_FAULT,
         NAI_DT_STATUS_CRC_FAULT
   */

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf("\n");
      printf("  ----------------- Status ----------------------------------------------------------\n");
      printf("  MinLo   MidRng  MaxHi  Low-Hi   Hi-Lo    BIT     OC   Summary  Watchdog  Inter-FPGA\n");
      printf(" ------- -------- ------ ------- -------- ------ ------ -------  --------  ----------\n");
   }
   else
   {
      printf("\n");
      printf("  ----------------- Status ----------------------------\n");
      printf("  MinLo   MidRng  MaxHi  Low-Hi   Hi-Lo    BIT     OC  \n");
      printf(" ------- -------- ------ ------- -------- ------ ------\n");
   }

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MIN_LO_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MID_RANGE_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MAX_HI_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, &status));
   printf("  %3i   ", status);

   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_SUMMARY_LATCHED, &status));
      printf(" %3i    ", status);

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED, &status));
      printf("  %3i    ", status);

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_CRC_FAULT_LATCHED, &status));
      printf("    %3i ", status);
   }

   printf("\n\n");

   return NAI_ERROR_UNKNOWN;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_IOFormat handles the user request to configure the Input/Output configuration for the selected
channel and calls the method in the naibrd library to set the Input/Output mode.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_IOFormat(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t bUpdateIOCfg = FALSE;
   uint32_t state = 0;
   int8_t iofmtreq;
   uint32_t ModuleID;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = p_dt_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   /*  Set I/O format configuration for channel. Available configurations include:
            NAI_DT_IOFORMAT_INPUT
            NAI_DT_IOFORMAT_OUTPUT_LOW
            NAI_DT_IOFORMAT_OUTPUT_HIGH
            NAI_DT_IOFORMAT_OUTPUT_PUSHPULL
   */
   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if (configurable_DT_IOFormat(ModuleID,chan))
   {
      printf("Type the desired IO configuration ");
      if (ModuleID == NAI_MODULE_ID_KA || ModuleID == NAI_MODULE_ID_KB )
         printf("(i=input,l=low side output): ");
      else
         printf("(i=input,l=low side output,h=high side output,p=push-pull output): ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt > 0)
         {
            iofmtreq = (int8_t)toupper(inputBuffer[0]);
            if (iofmtreq == 'I')
            {
               state = NAI_DT_IOFORMAT_INPUT;
               bUpdateIOCfg = TRUE;
            }
            else if (iofmtreq == 'L')
            {
               state = NAI_DT_IOFORMAT_OUTPUT_LOW;
               bUpdateIOCfg = TRUE;
            }
            else
            {
               if (ModuleID == NAI_MODULE_ID_KA || ModuleID == NAI_MODULE_ID_KB )
                  printf("ERROR: Invalid I/O Format Entry\n");
               else if (iofmtreq == 'H')
               {
                  state = NAI_DT_IOFORMAT_OUTPUT_HIGH;
                  bUpdateIOCfg = TRUE;
               }
               else if (iofmtreq == 'P')
               {
                  state = NAI_DT_IOFORMAT_OUTPUT_PUSHPULL;
                  bUpdateIOCfg = TRUE;
               }
               else
                  printf("ERROR: Invalid I/O Format Entry\n");
            }
         }
         if (!bQuit)
         {
            if (bUpdateIOCfg)
               check_status(naibrd_DT_SetIOFormat(cardIndex, module, chan, state));
         }
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_OutputState handles the user request to set the Output state for the selected
channel and calls the method in the naibrd library to set the Output state.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_OutputState(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
   bool_t bQuit = FALSE;
   bool_t bUpdateOutput = FALSE;
   nai_dt_state_t outputstate = 0;
   uint32_t ModuleID;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   /* Set the output state (high or low) on output channels.
      This is not applicable for channels configured as inputs.
   */
   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if (configurable_DT_Output(ModuleID, chan))
   {
      printf("\nType the desired output state ");
      printf("(l=low output,h=high output): ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt > 0)
         {
            switch (toupper(inputBuffer[0]))
            {
            case 'L':
               outputstate = 0;
               bUpdateOutput = TRUE;
               break;
            case 'H':
               outputstate=  1;
               bUpdateOutput = TRUE;
               break;
            default:
               printf("ERROR: Invalid Output State Format Entry\n");
               break;
            }
         }
      }
      if (!bQuit)
      {
         if (bUpdateOutput)
            check_status(naibrd_DT_SetOutputState(cardIndex, module, chan, outputstate));
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_ChanStatusEnable handles the user request to set the channel status reporting
enabled/disabled state for the selected channel and calls the method in the naibrd library
to set the channel status reporting enabled/disabled state.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_ChanStatusEnable(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t chanStatusEnable = FALSE;
   uint32_t ModuleID = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = p_dt_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf("\nSelect Channel Status Enabled/Disabled Setting to set: [0 (Disabled) or 1 (Enabled)]: ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if ((!bQuit) && (inputResponseCnt > 0))
      {
         if ((inputBuffer[0] == '0') || (inputBuffer[0] == '1'))
         {
            if (inputBuffer[0] == '1')
            {
               chanStatusEnable = TRUE;
            }
            check_status(naibrd_DT_SetChanStatusEnable(cardIndex, module, chan, chanStatusEnable));
         }
         else
         {
            printf("\nInvalid Setting Entered\n");
         }
      }
   }
   else
   {
      printf("\nModule does not support Channel Status Enable!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_FloatingPointEnable handles the user request to set the floating-point mode
enabled/disabled state for the module and calls the method in the naibrd library to set
the floating-point mode enabled/disabled state.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_FloatingPointEnable(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t floatModeEnable = FALSE;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\nSelect Floating-Point Mode Enabled/Disabled Setting to set: [0 (Disabled) or 1 (Enabled)]: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if ((!bQuit) && (inputResponseCnt > 0))
   {
      if ((inputBuffer[0] == '0') || (inputBuffer[0] == '1'))
      {
         if (inputBuffer[0] == '1')
         {
            floatModeEnable = TRUE;
         }
         check_status(naibrd_SetFloatingPointModeEnable(cardIndex, module, floatModeEnable));
      }
      else
      {
         printf("\nInvalid Setting Entered\n");
      }
   }


   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_ClearAllStatuses handles the user request to clear all latched statuses for the selected
channel and calls the method in the naibrd library to clear the latched statuses.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_ClearAllStatuses(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_bit_t status = 0u;
   uint32_t ModuleID = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = p_dt_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   printf("\nAre you sure you want to clear all Latched Statuses for channel %d? (Y for Yes or N for No): ", chan);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if ((!bQuit) && (inputResponseCnt > 0) && (toupper(inputBuffer[0]) == 'Y'))
   {
      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MAX_HI_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_MAX_HI_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MIN_LO_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_MIN_LO_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_MID_RANGE_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_MID_RANGE_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED));
      }
      status = 0u;

      check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, &status));
      if (status == 1u)
      {
         check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_HI_LO_TRANS_LATCHED));
      }
      status = 0u;

      if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
      {
         check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED, &status));
         if (status == 1u)
         {
            check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED));
         }
         status = 0u;

         check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_CRC_FAULT_LATCHED, &status));
         if (status == 1u)
         {
            check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_CRC_FAULT_LATCHED));
         }
         status = 0u;

         check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_SUMMARY_LATCHED, &status));
         if (status == 1u)
         {
            check_status(naibrd_DT_ClearStatus(cardIndex, module, chan, NAI_DT_STATUS_SUMMARY_LATCHED));
         }
      }
      Display_DT_Status(paramCount, p_params);
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_MinLoThreshold calls the Configure_DT_Threshold() routine for Min Low Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DT_MinLoThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   return Configure_DT_Threshold(p_dsw_params->cardIndex, p_dsw_params->module, p_dsw_params->channel, NAI_DT_THRESH_MIN_LO, (int8_t *)"Min Low");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_LowThreshold calls the Configure_DT_Threshold() routine for Lower Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DT_LowThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   return Configure_DT_Threshold(p_dsw_params->cardIndex, p_dsw_params->module, p_dsw_params->channel, NAI_DT_THRESH_LOWER, (int8_t *)"Lower");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_UpperThreshold calls the Configure_DT_Threshold() routine for Upper Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DT_UpperThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   return Configure_DT_Threshold(p_dsw_params->cardIndex, p_dsw_params->module, p_dsw_params->channel, NAI_DT_THRESH_UPPER, (int8_t *)"Upper");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_MaxHiThreshold calls the Configure_DT_Threshold() routine for Max High Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DT_MaxHiThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   return Configure_DT_Threshold(p_dsw_params->cardIndex, p_dsw_params->module, p_dsw_params->channel, NAI_DT_THRESH_MAX_HI, (int8_t *)"Max High");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_Threshold handles the user request to configure the selected threshold configuration and
channel and calls the method in the naibrd library to set the threshold voltage.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DT_Threshold(int32_t cardIndex, int32_t module, int32_t chan, nai_dt_thresh_type_t thresholdtype, int8_t* thresholdtext)
{
   bool_t bQuit = FALSE;
   float64_t threshold= 0.0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter the desired %s threshold voltage : ", thresholdtext);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         threshold = atof((const char *)inputBuffer);
         check_status(naibrd_DT_SetThreshold(cardIndex, module, chan, thresholdtype, threshold));
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_BITErrorThreshold handles the user request to set the BIT Error Threshold for
the module and calls the method in the naibrd library to set the BIT Error Threshold.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_BITErrorThreshold(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t ModuleID = 0u;
   uint32_t bitErrThres = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf("\nEnter the desired BIT Error Threshold : ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if ((!bQuit) && (inputResponseCnt > 0))
      {
         if (inputBuffer[0] == '-')
         {
            printf("\nInvalid value entered\n");
         }
         else
         {
            bitErrThres = (uint32_t)strtoul((const char*)inputBuffer, NULL, 10);
            if (bitErrThres == 0u)
            {
               if (inputBuffer[0] == '0')
               {
                  check_status(naibrd_DT_SetModuleBITErrorThreshold(cardIndex, module, bitErrThres));
               }
               else
               {
                  printf("\nInvalid value entered\n");
               }
            }
            else
            {
               check_status(naibrd_DT_SetModuleBITErrorThreshold(cardIndex, module, bitErrThres));
            }
         }
      }
   }
   else
   {
      printf("\nModule does not support BIT Error Threshold!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_CheckPBITComplete handles the user request to check the module power-on BIT completed state
and calls the method in the naibrd library to check the power-on BIT completed state. If the power-on BIT
completed state is set, meaning that power-on BIT has completed, the Latched BIT Status of each channel
is checked by calling the method in the naibrd library to read the BIT Status.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_CheckPBITComplete(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t ModuleID = 0u;
   int32_t channelCount = 0;
   bool_t pBitComplete = FALSE;
   nai_status_bit_t bitStatus = 0u;
   char strBitStatus[12] = "";
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = 0;

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

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      channelCount = naibrd_DT_GetChannelCount(ModuleID);

      /* Check to see if PBIT ran for the module. */
      printf("\nChecking if the Power-On BIT test has run...\n");
      check_status(naibrd_DT_CheckPowerOnBITComplete(cardIndex, module, &pBitComplete));
      switch (pBitComplete)
      {
         case 0u:
            printf("\nPBIT Complete: NOT COMPLETED\n");
         break;
         case 1u:
            printf("\nPBIT Complete: COMPLETED\n");
         break;
         default:
            printf("\nPBIT Complete: UNKNOWN\n");
         break;
      }

      if (pBitComplete)
      {
         /* Read the BIT status */
         printf("\nChecking the result of the Power-on BIT test...\n");
         for (chan = 1; chan <= channelCount; chan++)
         {
            check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_BIT_LATCHED, &bitStatus));
            switch (bitStatus)
            {
               case (nai_status_bit_t)0u:
                  sprintf(strBitStatus, "BIT Passed");
               break;
               case (nai_status_bit_t)1u:
                  sprintf(strBitStatus, "BIT FAILED");
               break;
               default:
                  sprintf(strBitStatus, "Unknown");
               break;
            }
            printf("Ch. %d: %s\n", chan, strBitStatus);
         }
      }
   }
   else
   {
      printf("\nModule does not support Power-On BIT!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DT_ClearModuleBITLogic handles the user request to clear the module BIT logic,
which resets the Continuous BIT internal circuitry and counter, and calls the method
in the naibrd library to clear the module BIT logic.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DT_ClearModuleBITLogic(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t ModuleID = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = p_dt_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      printf("\nAre you sure you want to reset the Continuous BIT internal circuitry and counter? (Y for Yes or N for No): ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if ((!bQuit) && (inputResponseCnt > 0) && (toupper(inputBuffer[0]) == 'Y'))
      {
         check_status(naibrd_DT_ClearModuleBITLogic(cardIndex, module, chan));
      }
   }
   else
   {
      printf("\nModule does not support clearing of BIT logic!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
configurable_DT_IOFormat determines whether the channel selected for the given Discrete Module ID is capable
of being programmed for high side and push-pull output configurations.
</summary>
*/
/**************************************************************************************************************/
static bool_t configurable_DT_IOFormat(uint32_t ModuleID, int32_t chan)
{
   bool_t configurable = TRUE;
   if ((ModuleID == NAI_MODULE_ID_KA) && ((chan < 13) || (chan > 16)))
      configurable = FALSE;
   return configurable;
}

/**************************************************************************************************************/
/**
<summary>
configurable_DT_Output determines whether the channel selected for the given Discrete Module ID is capable
of being configured as an output channel.
</summary>
*/
/**************************************************************************************************************/
static bool_t configurable_DT_Output(uint32_t ModuleID, int32_t chan)
{
   bool_t configurable = TRUE;
   if ((ModuleID == NAI_MODULE_ID_KA) && (chan > 16))
      configurable = FALSE;
   return configurable;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_WatchdogShowMenu displays the menu for watchdog commands.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_WatchdogShowMenu(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   uint32_t ModuleID = 0u;
   int32_t cmd = 0;
   int32_t numMenuCmds = 0;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int32_t chan = p_dt_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      numMenuCmds = DT_WD_CMD_COUNT;
      naiapp_utils_LoadParamMenuCommands(numMenuCmds, DT_WatchdogOpMenuCmds);
      while (bContinue)
      {
         Handle_DT_DisplayWatchdog(cardIndex, module, chan);
         naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_WD_PGM_NAME);
         printf("\nType DT Watchdog command or %c to quit : main > watchdog >", 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 = FALSE;
               }
               else
               {
                  bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
                  if (bCmdFound)
                  {
                     DT_WatchdogOpMenuCmds[cmd].func(paramCount, p_params);
                  }
                  else
                  {
                     printf("\nInvalid command entered\n");
                  }
               }
            }
         }
         else
            bContinue = FALSE;
      }
      numMenuCmds = DT_BASICOP_CMD_COUNT;
      naiapp_utils_LoadParamMenuCommands(numMenuCmds, DT_BasicOpMenuCmds);
   }
   else
   {
      printf("\nModule does not support Watchdog Timer!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_WatchDogQuietTime handles the user request to set the watchdog quiet time for the module and calls
the method in the naibrd library to set the watchdog quiet time. The user is prompted for the value in ms.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_WatchDogQuietTime(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t quietTime = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\r\n*** To use this sample strobe it is recommended to set a quiet time > 500 ms **");
   printf("\r\nEnter the desired Watchdog Quiet Time (ms): ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         if (inputBuffer[0] == '-')
         {
            printf("\nInvalid value entered\n");
         }
         else
         {
            quietTime = atoi((const char *)inputBuffer);
            if (quietTime == 0u)
            {
               if (inputBuffer[0] == '0')
               {
                  check_status(naibrd_DT_SetWatchdogQuietTime(cardIndex, module, quietTime * 1000));
               }
               else
               {
                  printf("\nInvalid value entered\n");
               }
            }
            else
            {
               check_status(naibrd_DT_SetWatchdogQuietTime(cardIndex, module, quietTime * 1000));
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_WatchDogWindowTime handles the user request to set the watchdog window time for the module and calls
the method in the naibrd library to set the watchdog window time. The user is prompted for the value in ms.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_WatchDogWindowTime(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t windowTime = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\r\n*** To use this sample strobe it is recommended to set a window time > 500 ms **");
   printf("\r\nEnter the desired Watchdog Window Time (ms): ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         if (inputBuffer[0] == '-')
         {
            printf("\nInvalid value entered\n");
         }
         else
         {
            windowTime = atoi((const char *)inputBuffer);
            if (windowTime == 0u)
            {
               if (inputBuffer[0] == '0')
               {
                  check_status(naibrd_DT_SetWatchdogWindow(cardIndex, module, windowTime * 1000));
               }
               else
               {
                  printf("\nInvalid value entered\n");
               }
            }
            else
            {
               check_status(naibrd_DT_SetWatchdogWindow(cardIndex, module, windowTime * 1000));
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_DisplayWatchdog displays the DT Watchdog Operations data. The data is retrieved by calling the
methods in the naibrd library to retrieve the data.
</summary>
*/
/**************************************************************************************************************/
static bool_t Handle_DT_DisplayWatchdog(int32_t cardIndex, int32_t module, int32_t chan)
{
   nai_status_bit_t wdStatLatched = 0u;
   nai_status_bit_t wdStatRT = 0u;
   uint32_t windowTime = 0u;
   uint32_t quietTime = 0u;

   printf("\n\nDT Watchdog Data:\n");
   check_status(naibrd_DT_GetWatchdogQuietTime(cardIndex, module, &quietTime));
   quietTime = quietTime / 1000;
   printf("Quiet Time: %d mS\n", quietTime);
   check_status(naibrd_DT_GetWatchdogWindow(cardIndex, module, &windowTime));
   windowTime = windowTime / 1000;
   printf("Window Time: %d mS\n", windowTime);

   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_LATCHED, &wdStatLatched));
   check_status(naibrd_DT_GetStatus(cardIndex, module, chan, NAI_DT_STATUS_WATCHDOG_TIMER_FAULT_REALTIME, &wdStatRT));
   printf("WatchDog Status (R/L):  (%1d/%1d)\n", wdStatRT, wdStatLatched);

   printf("\n");

   return 0u;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_StrobeWatchdog will start a thread to continuously Strobe the watchdog.
The Watchdog Strobe is done by calling the method in the naibrd library to strobe the watchdog.
NOTE: When this thread/application exits, the module will shut off all outputs and will need to
      be power cycled in order to be operational.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_StrobeWatchdog(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   int32_t* arg = (int32_t*)malloc(sizeof(int32_t) * 3);
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\r\n**NOTE: When this thread/application exits, the module will shut off all outputs and will need to be power cycled in order to be operational **");
   printf("\r\nEnter Y if you want to continue and N to go back: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         if ((inputBuffer[0] == 'Y') || (inputBuffer[0] == 'y'))
         {
            printf("\r\nStrobing Watchdog every (QuietTime) + (Window)/2...");
            printf("\r\nStarting thread...");
            /* Spawn thread here */

            arg[0] = cardIndex;
            arg[1] = module;

#if defined (__VXWORKS__)
            if (thread == 0)
#elif defined (LINUX)
            if (thread == (pthread_t)NULL)
#else
            if (thread == (int32_t*)NULL)
#endif
            {
#if defined (WIN32)
               LPDWORD threadID = 0;
               thread = CreateThread(NULL, 0, WD_Strobe_ThreadEntryPoint, arg, 0, threadID);
#elif defined (LINUX)
               pthread_create(&thread, NULL, WD_Strobe_ThreadEntryPoint, arg);
#elif defined (__VXWORKS__)
               thread = taskSpawn("WD_Strobe_Thread", 100, 0, 10000, (FUNCPTR)WD_Strobe_ThreadEntryPoint, (int32_t)arg, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#else
#error Unsupported OS
#endif
               if (thread != 0) {}
               else
               {
                  free(arg);
                  printf("\nFailed to Create Thread");
               }
            }
            else
            {
#if defined (WIN32)
               LPDWORD threadID = 0;
#endif
               /* kill previous thread and create new one. Report this to them. */
               naiapp_kill_WDStrobe_Thread();
#if defined (WIN32)
               thread = CreateThread(NULL, 0, WD_Strobe_ThreadEntryPoint, arg, 0, threadID);
#elif defined (LINUX)
               pthread_create(&thread, NULL, WD_Strobe_ThreadEntryPoint, arg);
#elif defined (__VXWORKS__)
               thread = taskSpawn("WD_Strobe_Thread", 100, 0, 10000, (FUNCPTR)WD_Strobe_ThreadEntryPoint, (int32_t)arg, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#else
#error Unsupported OS
#endif

#if defined (__VXWORKS__)
               if (thread != 0) {}
#elif defined (LINUX)
               if (thread != (pthread_t)NULL) {}
#else
               if (thread != (int32_t*)NULL) {}
#endif
               else
               {
                  free(arg);
                  printf("\nFailed to Create Thread");
               }
            }
         }
         else
         {
            printf("\r\nReturning to Menu...");
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
naiapp_kill_WDStrobe_Thread will terminate the WD strobing thread. Module will shut off outputs
at this state and will need to be power cycled to be operational.
</summary>
*/
/**************************************************************************************************************/
static void naiapp_kill_WDStrobe_Thread()
{
#if defined (__VXWORKS__)
   if (thread != 0)
   {
      terminateThread = TRUE;
      thread = 0;
   }
#elif defined (LINUX)
   if (thread != ((pthread_t)NULL))
   {
      terminateThread = TRUE;
      thread = ((pthread_t)NULL);
   }
#else
   if (thread != ((int32_t*)NULL))
   {
      terminateThread = TRUE;
      thread = ((int32_t*)NULL);
   }
#endif
}

/**************************************************************************************************************/
/**
<summary>
WD_Strobe_ThreadEntryPoint will continuously loop, strobing the watchdog every QuietTime + Window/2.
</summary>
*/
/**************************************************************************************************************/
#if defined (WIN32)
DWORD WINAPI WD_Strobe_ThreadEntryPoint(LPVOID param)
#elif defined (LINUX)
void* WD_Strobe_ThreadEntryPoint(void* param)
#elif defined (__VXWORKS__)
static int WD_Strobe_ThreadEntryPoint(int32_t param)
#else
#error Unsupported OS
#endif
{
   uint32_t windowTime = 0u;
   uint32_t quietTime = 0u;
   int32_t delayTime = 0;
   int32_t* modInfo = (int32_t*)param;
   int32_t cardIndex = modInfo[0];
   int32_t module = modInfo[1];
   terminateThread = FALSE;
   free(modInfo);

   check_status(naibrd_DT_GetWatchdogQuietTime(cardIndex, module, &quietTime));
   check_status(naibrd_DT_GetWatchdogWindow(cardIndex, module, &windowTime));
   quietTime = quietTime / 1000;
   windowTime = windowTime / 1000;
   delayTime = quietTime + (windowTime / 2);
   check_status(naibrd_DT_WatchdogStrobe(cardIndex, module));
   do
   {
      nai_msDelay(delayTime);
      check_status(naibrd_DT_WatchdogStrobe(cardIndex, module));
   } while (!terminateThread);
   return NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_kill_WDStrobe_Thread will terminate the WD Strobing thread. Module will shut off outputs
at this state and will need to be power cycled to be operational.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_kill_WDStrobe_Thread(int32_t paramCount, int32_t* p_params)
{
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
   UNREFERENCED_PARAMETER(p_params);
#endif

   naiapp_kill_WDStrobe_Thread();
   return NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_ModulePowerResetMenu displays the menu for module power reset commands.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_ModulePowerResetMenu(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   uint32_t ModuleID = 0u;
   int32_t cmd = 0;
   int32_t numMenuCmds = 0;
   bool_t poweredDownStatus = 0u;
   bool_t notDetectedStatus = 0u;
   bool_t notLinkInitStatus = 0u;
   bool_t notFWNotStatus = 0u;
   bool_t commErrorStatus = 0u;
   bool_t resetRequest = 0u;
   bool_t powerDownRequest = 0u;
   bool_t powerUpRequest = 0u;
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   ModuleID = naibrd_GetModuleID(cardIndex, module);
   if ((ModuleID == NAI_MODULE_ID_DT1) || (ModuleID == NAI_MODULE_ID_DT4) || (ModuleID == NAI_MODULE_ID_DTB) || (ModuleID == NAI_MODULE_ID_CM1) || (ModuleID == NAI_MODULE_ID_CM2))
   {
      numMenuCmds = DT_MODULE_POWER_RESET_CMD_COUNT;
      naiapp_utils_LoadParamMenuCommands(numMenuCmds, DT_ModulePowerResetMenuCmds);
      while (bContinue)
      {
         printf("\n\n\n");
         printf(" -----------------------------Status------------------------------    ----------Request----------\n");
         printf(" Powered Down  Not Detected  Not Link Init  Not FW Not  Comm Error    Reset  Power Down  Power Up\n");
         printf(" ------------  ------------  -------------  ----------  ----------    -----  ----------  --------\n");
         check_status(naibrd_DT_GetModulePowerResetStatus(cardIndex, module, NAI_DT_MODULE_POWER_RESET_STATUS_POWERED_DOWN, &poweredDownStatus));
         check_status(naibrd_DT_GetModulePowerResetStatus(cardIndex, module, NAI_DT_MODULE_POWER_RESET_STATUS_NOT_DETECTED, &notDetectedStatus));
         check_status(naibrd_DT_GetModulePowerResetStatus(cardIndex, module, NAI_DT_MODULE_POWER_RESET_STATUS_NOT_LINK_INIT, &notLinkInitStatus));
         //check_status(naibrd_DT_GetModulePowerResetStatus(cardIndex, module, NAI_DT_MODULE_POWER_RESET_STATUS_NOT_FW_NOT, &notFWNotStatus));
         check_status(naibrd_DT_GetModulePowerResetStatus(cardIndex, module, NAI_DT_MODULE_POWER_RESET_STATUS_COMM_ERROR, &commErrorStatus));
         check_status(naibrd_DT_GetModulePowerReset(cardIndex, module, NAI_DT_MODULE_POWER_RESET_REQUEST_RESET, &resetRequest));
         check_status(naibrd_DT_GetModulePowerReset(cardIndex, module, NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_DOWN, &powerDownRequest));
         check_status(naibrd_DT_GetModulePowerReset(cardIndex, module, NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_UP, &powerUpRequest));
         printf("      %1d             %1d              %1d            %1d           %1d           %1d        %1d          %1d\n",
                poweredDownStatus, notDetectedStatus, notLinkInitStatus, notFWNotStatus, commErrorStatus, resetRequest, powerDownRequest, powerUpRequest);
         naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_MODULE_POWER_RESET_PGM_NAME);
         printf("\nType DT 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 = FALSE;
               }
               else
               {
                  bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
                  if (bCmdFound)
                  {
                     DT_ModulePowerResetMenuCmds[cmd].func(paramCount, p_params);
                  }
                  else
                  {
                     printf("\nInvalid command entered\n");
                  }
               }
            }
         }
         else
            bContinue = FALSE;
      }
      numMenuCmds = DT_BASICOP_CMD_COUNT;
      naiapp_utils_LoadParamMenuCommands(numMenuCmds, DT_BasicOpMenuCmds);
   }
   else
   {
      printf("\nModule does not support Module Power Reset!\n");
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_ClearModulePowerResetStatus handles the user request to clear the module power reset status
and calls the method in the naibrd library to clear the module power reset status. The user is
prompted for the module power reset status type to clear.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_ClearModulePowerResetStatus(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_dt_module_power_reset_status_type_t statusTypeToClear = 0u;
   bool_t modulePowerResetStatusRead = 0u;
   char statusTypeStr[14] = "";
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\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 = NAI_DT_MODULE_POWER_RESET_STATUS_POWERED_DOWN;
            sprintf(statusTypeStr, "Powered Down");
         break;
         case '1':
            statusTypeToClear = NAI_DT_MODULE_POWER_RESET_STATUS_NOT_DETECTED;
            sprintf(statusTypeStr, "Not Detected");
         break;
         case '2':
            statusTypeToClear = NAI_DT_MODULE_POWER_RESET_STATUS_NOT_LINK_INIT;
            sprintf(statusTypeStr, "Not Link Init");
         break;
         /*case '3':
            statusTypeToClear = NAI_DT_MODULE_POWER_RESET_STATUS_NOT_FW_NOT;
            sprintf(statusTypeStr, "Not FW Not");
         break;*/
         case '4':
            statusTypeToClear = NAI_DT_MODULE_POWER_RESET_STATUS_COMM_ERROR;
            sprintf(statusTypeStr, "Comm Error");
         break;
         case 'q':
         case 'Q':
            bQuit = TRUE;
         break;
         default:
            bQuit = TRUE;
            printf("\nInvalid module power reset status type entered\n");
         break;
      }

      if (!bQuit)
      {
         printf("\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_DT_GetModulePowerResetStatus(cardIndex, module, statusTypeToClear, &modulePowerResetStatusRead));
            if (modulePowerResetStatusRead == 1u)
            {
               check_status(naibrd_DT_ClearModulePowerResetStatus(cardIndex, module, statusTypeToClear));
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Handle_DT_SetModulePowerReset handles the user request to set the module power reset request
and calls the method in the naibrd library to set the module power reset request. The user is
prompted for the module power reset request type to set, and then the user is prompted to set
or reset the request bit.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Handle_DT_SetModulePowerReset(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_dt_module_power_reset_type_t resetTypeToSet = 0u;
   char resetTypeStr[11] = "";
   p_naiapp_AppParameters_t p_dt_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dt_params->cardIndex;
   int32_t module = p_dt_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   printf("\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 = NAI_DT_MODULE_POWER_RESET_REQUEST_RESET;
            sprintf(resetTypeStr, "Reset");
         break;
         case '1':
            resetTypeToSet = NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_DOWN;
            sprintf(resetTypeStr, "Power Down");
         break;
         case '2':
            resetTypeToSet = NAI_DT_MODULE_POWER_RESET_REQUEST_POWER_UP;
            sprintf(resetTypeStr, "Power Up");
         break;
         case 'q':
         case 'Q':
            bQuit = TRUE;
         break;
         default:
            bQuit = TRUE;
            printf("\nInvalid module power reset request type entered\n");
         break;
      }

      if (!bQuit)
      {
         printf("\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_DT_SetModulePowerReset(cardIndex, module, resetTypeToSet, (bool_t)FALSE));
            }
            else if (inputBuffer[0] == '1')
            {
               check_status(naibrd_DT_SetModulePowerReset(cardIndex, module, resetTypeToSet, (bool_t)TRUE));
            }
            else
            {
               printf("\nInvalid selection entered\n");
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

Help Bot

X