DS BITTest Sample Application (SSK 1.x)

Overview

The DS BITTest sample application demonstrates how to exercise the built-in test (BIT) modes on synchro/resolver (D/S) modules using the NAI Software Support Kit (SSK 1.x). It covers the core diagnostic operations you will need in your own application: enabling and disabling the on-line (D2) and off-line (D3) background tests, setting the test verify value, configuring channel output angles, reading measured angles and voltages, reading module status flags, and controlling channel power and active state.

D/S modules provide two background test modes. The D2 on-line test runs while the module is actively converting — it injects a known reference and verifies the conversion path without taking the channel offline. The D3 off-line test takes the channel offline for a more thorough diagnostic. Both tests compare their result against a configurable test verify value, and failures are reported through the BIT status flag.

This sample supports all DS module types (see the DS1-DSN Manual for module variants and specifications). It serves as a practical API reference — each menu command maps directly to one or more naibrd_DS_*() API calls that you can lift into your own code.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a DS module installed.
  • 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 DS_BITTest executable from your build output directory. On startup the application looks for a configuration file (default_DsBitTest.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 select a module and channel, then exercise the BIT test operations.

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 DS. 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_DsBitTest.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 DS variant installed.
#if defined (__VXWORKS__)
int32_t DS_RunBitProgramSample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t moduleCnt;
   int32_t cardIndex;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)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))
                  DS_RunAngleProgram(cardIndex, module, moduleID, moduleCnt);
               else
                  printf(" *** Module selection not recognized as valid module type. ***\n\n");
            }
            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 DS 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 DS_RunBitProgramSample() — the SSK 1.x build system selects the correct variant via a preprocessor guard:

#if defined (__VXWORKS__)
int32_t DS_RunBitProgramSample(void)
#else
int32_t main(void)
#endif

Command Loop

DS_RunAngleProgram() presents a top-level menu where the user selects a module, channel, and then enters the BIT test function via the BIT command. The function retrieves the channel count for the selected module using naibrd_DS_GetChannelCount(), then enters a command loop:

channelCount = naibrd_DS_GetChannelCount(moduleID);
do
{
   Show_DSDemoFunc_Commands();
   printf("\nType DS command or %c to quit : ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      for (cmdIdx = 0; cmdIdx < DS_FUNC_CMD_COUNT; cmdIdx++)
      {
         if (0 == naiapp_strnicmp((const int8_t*)inputBuffer,
            (const int8_t*)DS_DemoFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
            break;
      }
      switch (cmdIdx)
      {
      case DS_FUNC_CMD_SET_ANGLE:
         if ((module > 0) && (channel > 0))
            DS_RunBitTestFunc(cardIndex, module, channel);
         break;
      case DS_FUNC_CMD_SET_MODULE:
         /* prompt for module number */
         break;
      case DS_FUNC_CMD_SET_CHANNEL:
         /* prompt for channel number */
         break;
      }
   }
} while (bQuit == FALSE);

The top-level commands are:

CommandDescription
BITEnter the BIT test submenu for the selected module and channel
MSelect module
CSelect channel

Once the user enters the BIT submenu via DS_RunBitTestFunc(), a second command loop displays the current channel state and dispatches user commands:

CommandDescription
ANGSet output angle
D2Enable/disable on-line (D2) background test
D3Enable/disable off-line (D3) background test
VERIFYSet test verify value
ACTSet active channel enable/disable
PWRSet power enable/disable
UPDATERefresh the status display

The menu-driven structure is a convenience of the sample application. In your own application, you would call the same underlying naibrd_DS_*() API functions directly.

Reading Channel Status

Before running BIT tests, the sample displays a comprehensive status line for the selected channel via DS_ShowSetAngleTestResult(). This function reads the programmed angle, measured angle, D2/D3 test state, ratio/fixed mode, test verify value, measured voltages and frequency, status flags, active channel state, and power state. To read the same information in your own application, call the following API functions.

Read Angles

To read the programmed output angle and the measured angle for a channel:

float64_t setAngle, measAngle;
 
naibrd_DS_GetAngle(cardIndex, module, channel, NAI_DS_ANGLE_SINGLE, &setAngle);
naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_ANGLE, &measAngle);
  • NAI_DS_ANGLE_SINGLE — reads the single-speed (non-multi-speed) programmed angle.
  • NAI_DS_MEASURED_ANGLE — reads the hardware-measured angle from the synchro/resolver input.

Read Measured Voltages and Frequency

To read the signal voltage (VLL), reference voltage (VRef), and reference frequency from the hardware:

float64_t vll, vref, refFreq;
 
naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_SIGNAL_VOLTAGE, &vll);
naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_REF_VOLTAGE, &vref);
naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_REF_FREQUENCY, &refFreq);

These values reflect what the D/S module is actually seeing on its inputs. If no external synchro/resolver is connected, VLL and VRef will read near zero.

Read D2/D3 Test State and Ratio/Fixed Mode

To check whether the on-line and off-line BIT tests are currently enabled, and which output mode is active:

uint8_t d2Enabled, d3Enabled;
uint32_t ratioFixed, testVerify;
 
naibrd_DS_GetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, &d2Enabled);
naibrd_DS_GetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, &d3Enabled);
naibrd_DS_GetRatioFixedMode(cardIndex, module, channel, &ratioFixed);
naibrd_DS_GetTestVerify(cardIndex, module, &testVerify);
  • d2Enabled / d3EnabledNAI_ENABLE (1) if the test is active, NAI_DISABLE (0) if not.
  • ratioFixedNAI_DS_OUTPUT_RATIO or NAI_DS_OUTPUT_FIXED.
  • testVerify — the 16-bit reference word used by the D2 test logic.

Read Module Status Flags

The sample reads four latched status flags that indicate fault conditions on the channel. Each flag returns NAI_DS_MODULE_STATUS_GOOD when the condition is healthy:

uint32_t signalLoss, refLoss, bitLoss, phaseLoss;
 
naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_SIGNAL_LOST, &signalLoss);
naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_REFERENCE_LOST, &refLoss);
naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_BIT_LOST, &bitLoss);
naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_PHASE_LOST, &phaseLoss);

The sample formats these as a compact S/R/B/P string where 0 indicates good and 1 indicates a fault:

  • S — signal loss (no synchro/resolver signal voltage detected)
  • R — reference loss (no reference voltage detected)
  • B — BIT loss (built-in test failure)
  • P — phase loss (signal and reference are out of expected phase relationship)

Read Active Channel and Power State

uint8_t activeState, powerState;
 
naibrd_DS_GetActiveChannel(cardIndex, module, channel, &activeState);
naibrd_DS_GetPowerEnable(cardIndex, module, channel, &powerState);

Both calls return NAI_ENABLE or NAI_DISABLE. A channel must be both powered on and set active before it will produce valid angle measurements.

Important

Common Errors

  • Status shows signal/reference loss — no external synchro/resolver signal is connected, or the signal voltage is below the threshold. Connect the expected signal source and verify voltage levels against the DS1-DSN Manual.
  • All measured values read zero — the channel may not be powered on or not set as active. Call naibrd_DS_SetPowerEnable() and naibrd_DS_SetActiveChannel() first.

BIT Test Configuration

This section covers the API calls used to configure and run the D/S module’s built-in test modes. The D2 and D3 tests are the primary diagnostic tools for verifying the synchro/resolver conversion path.

Set Angle

To set the output angle on a channel in your own application, call naibrd_DS_SetAngle(). During BIT testing, setting a known angle lets you verify that the measured angle matches the programmed value:

float64_t angle = 45.0;
naibrd_DS_SetAngle(cardIndex, module, channel, NAI_DS_ANGLE_SINGLE, angle);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • channel — the channel to configure.
  • NAI_DS_ANGLE_SINGLE — specifies single-speed angle mode.
  • angle — the desired angle in degrees (0.0 to 359.9954).

Enable/Disable On-Line (D2) Test

The D2 on-line background test runs while the module is actively converting, allowing you to verify the conversion path without taking the channel offline. The D2 test injects a known reference and compares the result against the test verify value. To enable or disable this test in your own application, call naibrd_DS_SetTestModeEnable():

/* Enable the D2 on-line test */
naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, (uint8_t)NAI_ENABLE);
 
/* Disable the D2 on-line test */
naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, (uint8_t)NAI_DISABLE);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • NAI_DS_ON_LINE_TEST — selects the D2 (on-line) test mode.
  • The enable parameter is NAI_ENABLE (1) or NAI_DISABLE (0).

Note

The D2 test is a module-wide setting, not per-channel. Enabling D2 affects all channels on the module.

Enable/Disable Off-Line (D3) Test

The D3 off-line background test takes the channel offline to perform a more thorough diagnostic of the conversion path. To enable or disable this test:

/* Enable the D3 off-line test */
naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, (uint8_t)NAI_ENABLE);
 
/* Disable the D3 off-line test */
naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, (uint8_t)NAI_DISABLE);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • NAI_DS_OFF_LINE_TEST — selects the D3 (off-line) test mode.

Note

When D3 is enabled, channel output is interrupted. Only enable D3 when the channel is not being used for active synchro/resolver control. The D3 test is also a module-wide setting.

Set Test Verify Value

The test verify value is a reference word that the BIT logic compares against during the D2 test. To set this value in your own application:

uint32_t verifyValue = 0x1234;
naibrd_DS_SetTestVerify(cardIndex, module, verifyValue);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • verifyValue — a 16-bit value (0 to 65535) used as the BIT comparison reference.

Note

The test verify value is a module-wide setting. Consult the DS1-DSN Manual for details on how this value is used during the D2 test and what values to expect for your module variant.

Set Active Channel

To enable or disable a specific channel in your own application, call naibrd_DS_SetActiveChannel(). A channel must be set active before it produces valid measurements:

/* Enable channel */
naibrd_DS_SetActiveChannel(cardIndex, module, channel, (uint8_t)NAI_ENABLE);
 
/* Disable channel */
naibrd_DS_SetActiveChannel(cardIndex, module, channel, (uint8_t)NAI_DISABLE);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • channel — the channel to enable or disable.
  • The fourth parameter — NAI_ENABLE (1) to activate, NAI_DISABLE (0) to deactivate.

Set Power Enable

To turn power on or off for a channel, call naibrd_DS_SetPowerEnable(). The channel must be powered on before any conversion or test can operate:

/* Power on */
naibrd_DS_SetPowerEnable(cardIndex, module, channel, (uint8_t)NAI_ENABLE);
 
/* Power off */
naibrd_DS_SetPowerEnable(cardIndex, module, channel, (uint8_t)NAI_DISABLE);
  • cardIndex — identifies the board.
  • module — the slot containing the DS module.
  • channel — the channel to control.
  • The fourth parameter — NAI_ENABLE (1) to power on, NAI_DISABLE (0) to power off.

Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — Returned if the selected module does not support the requested test mode or feature.
  • Angle out of range — The angle value must be between 0.0 and 359.9954 degrees.
  • BIT status shows failure after enabling D2 — This can be normal during the initial test cycle. The D2 test needs time to stabilize after being enabled. Allow the test to complete before reading the BIT status. Consult the DS1-DSN Manual for expected BIT timing on your module.
  • Test verify value rejected — The value must be between 0 and 65535 (16-bit unsigned).

Troubleshooting Reference

Note

This section summarizes errors covered in the preceding sections. Consult the DS1-DSN Manual for hardware-specific diagnostics.

Error / SymptomPossible CausesSuggested Resolution
No board found or connection timeoutBoard not powered, incorrect or missing configuration file, network issueVerify hardware is powered and connected. If default_DsBitTest.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 recognized at selected slotSlot does not contain a DS moduleVerify module installation with the board menu
Invalid card or module indexWrong index values passedCards are zero-based, modules are one-based
BIT status stuck in failureD2/D3 test not fully completed, or test verify value does not match expected resultWait for the test cycle to complete; verify the test verify value matches module expectations
Status shows signal/reference lossNo external synchro/resolver signal connected, or signal below thresholdConnect the expected signal source and verify voltage levels
Measured angle reads zeroChannel not powered or not set activeEnable power and set the channel active before reading
Angle out of rangeValue outside 0.0-359.9954Correct the angle value
D3 test disrupts channel outputD3 takes the channel offline by designOnly enable D3 when the channel is not needed for active control

Full Source

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

Full Source -- DS_BITTest.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
 
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
 
/* naibrd include files */
#include "DS_Common.h"
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ds.h"
#include "advanced/nai_ether_adv.h"
 
static const int8_t *CONFIG_FILE = (int8_t *)"default_DsBitTest.txt";
 
/* Function prototypes */
static void DS_ShowSetAngleTestResult(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_RunAngleProgram(int32_t cardIndex, int32_t module, uint32_t moduleID, int32_t maxModule);
static void DS_RunBitTestFunc(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_SetNewAngle(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_SetD2Test(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_SetTestVerifyValue(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_SetPower(int32_t cardIndex, int32_t module, int32_t channel);
static void DS_SetActiveChannel(int32_t cardIndex, int32_t module, int32_t channel);
 
static void Show_DSDemoFunc_Commands(void);
static void DS_SetD3Test(int32_t cardIndex, int32_t module, int32_t channel);
static void printInvalidUserInputMessage(uint32_t uTypeIdx, float64_t dUserInput);
static void showCurrentModChan(int32_t nModule, int32_t nChannel);
static void getStatus(int32_t cardIndex, int32_t module, int32_t channel, uint8_t *u8Status);
 
static uint32_t getUserInput(void);
static bool_t checkUserInput(uint32_t uTypeIdx, float64_t dUserInput);
 
/****** Command Table *******/
enum dsfunc_commands
{
   DS_FUNC_CMD_SET_ANGLE,
   DS_FUNC_CMD_SET_MODULE,
   DS_FUNC_CMD_SET_CHANNEL,
   DS_FUNC_CMD_COUNT
};
/****** User Input Table *******/
enum dsfunc_userInputs
{
   DS_USER_INPUT_SET_ANGLE,
   DS_USER_INPUT_SET_D2,
   DS_USER_INPUT_SET_D3,
   DS_USER_INPUT_SET_TEST_VERIFY,
   DS_USER_INPUT_ACTIVE_CHAN,
   DS_USER_INPUT_POWER,
   DS_USER_INPUT_REFRESH,
   DS_USER_INPUT_QUIT,
   DS_USER_INVALID_INPUT,
   DS_USER_INPUT_COUNT
};
 
/* "what to type", "what is displayed", assigned cmd #, function called */
struct dsdemofunc_cmdtbl {
   int8_t *cmdstr;
   int8_t *menustr;
   int32_t  cmdnum;
   void(*func)(int32_t cardIndex, int32_t module, int32_t channel);
};
 
/* assigned cmd #, uppwer Limit, lower Limit*/
struct dsUserInputLimitTable {
   int32_t  cmdnum;
   int8_t *cmdstr;
   float64_t upperLimit;
   float64_t lowerLimit;
};
 
/****** Command Tables *******/
static struct dsdemofunc_cmdtbl DS_DemoFuncMenuCmds[] = {
   {(int8_t *)"BIT",  (int8_t *)"Run BIT ON/OFF LINE TEST",    DS_FUNC_CMD_SET_ANGLE,         DS_RunBitTestFunc},\
    {(int8_t *)"M ",  (int8_t *)"Select Module",               DS_FUNC_CMD_SET_MODULE,        NULL},\
    {(int8_t *)"C ",  (int8_t *)"Select Channel",              DS_FUNC_CMD_SET_CHANNEL,       NULL},\
   {NULL,             NULL,                                    0,                             NULL}
};
 
/****** User Input Command Tables *******/
static struct dsdemofunc_cmdtbl DS_DemoUserInputs[] = {
   { (int8_t *)"ANG    ",            (int8_t *)"Set Angle",                     DS_USER_INPUT_SET_ANGLE,             DS_SetNewAngle},
    {(int8_t *)"D2    ",             (int8_t *)"Set On-Line(D2) Test",          DS_USER_INPUT_SET_D2,                DS_SetD2Test},
    {(int8_t *)"D3    ",             (int8_t *)"Set On-Line(D3) Test",          DS_USER_INPUT_SET_D3,                DS_SetD3Test},
    {(int8_t *)"VERIFY",             (int8_t *)"Set Test Verify Value",         DS_USER_INPUT_SET_TEST_VERIFY,       DS_SetTestVerifyValue},
    {(int8_t *)"ACT    ",            (int8_t *)"Set Active Channel",            DS_USER_INPUT_ACTIVE_CHAN,           DS_SetActiveChannel},
    {(int8_t *)"PWR    ",            (int8_t *)"Set Power",                     DS_USER_INPUT_POWER,                 DS_SetPower},
    {(int8_t *)"UPDATE ",            (int8_t *)"Update",                        DS_USER_INPUT_REFRESH,               NULL},
    {(int8_t *)"Q      ",            (int8_t *)"Quit",                          DS_USER_INPUT_QUIT,                  NULL},
    {(int8_t *)"",                   (int8_t *)"",                              DS_USER_INVALID_INPUT,               NULL},
    {NULL,                          NULL,                                       0,                                   NULL}
};
 
static struct dsUserInputLimitTable DS_Inputs_Limits[] = {
    {DS_USER_INPUT_SET_ANGLE,             (int8_t *)"Angle",                      359.9954,   0.0},
    {DS_USER_INPUT_SET_D2,                (int8_t *)"D2 TestDisable/Enable",      1.0,        0.0},
    {DS_USER_INPUT_SET_D3,                (int8_t *)"D3 TestDisable/Enable",      1.0,        0.0},
    {DS_USER_INPUT_SET_TEST_VERIFY,       (int8_t *)"D2 Test Verify Value",       65535.0,    0.0},
    {DS_USER_INPUT_ACTIVE_CHAN,           (int8_t *)"Active Channel",             1.0,        0.0},
    {DS_USER_INPUT_POWER,                 (int8_t *)"Set Power",                  1.0,        0.0},
    {DS_USER_INPUT_REFRESH,               (int8_t *)"",                           0.0,        0.0},
    {DS_USER_INPUT_QUIT,                  (int8_t *)"",                           0.0,        0.0},
    {DS_USER_INVALID_INPUT,               (int8_t *)"",                           0.0,        0.0},
    {DS_USER_INPUT_COUNT,                 (int8_t *)"",                           0.0,        0.0}
};
 
#if defined (__VXWORKS__)
int32_t DS_RunBitProgramSample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t moduleCnt;
   int32_t cardIndex;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)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));
            /* Select Module */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
 
               if ((moduleID != 0))
               {
                  DS_RunAngleProgram(cardIndex, module, moduleID, moduleCnt);
               }
               else
               {
                  printf(" *** Module selection not recognized as valid module type for this application. ***\n\n");
               }
            }
 
            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;
}
 
static void DS_RunAngleProgram(int32_t cardIndex, int32_t module, uint32_t moduleID, int32_t maxModule)
{
   bool_t bQuit;
   int32_t channel = 0;
   int32_t channelCount;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   channelCount = naibrd_DS_GetChannelCount(moduleID);
   do
   {
      Show_DSDemoFunc_Commands();
      printf("\nType DS command or %c to quit : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         for (cmdIdx = 0; cmdIdx < DS_FUNC_CMD_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)DS_DemoFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }
         switch (cmdIdx)
         {
         case DS_FUNC_CMD_SET_ANGLE:
            if ((module > 0) && (channel > 0))
               DS_RunBitTestFunc(cardIndex, module, channel);
            break;
 
         case DS_FUNC_CMD_SET_MODULE:
            printf("\nEnter Module Number:\n");
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            module = atoi((const char *)inputBuffer);
            if ((module < 1) || (module > maxModule))
            {
               printf("\n%s: %d is outside the limits[%d - %d]", "Module #", module, 1, maxModule);
            }
            break;
 
         case DS_FUNC_CMD_SET_CHANNEL:
            printf("\nEnter Channel Number:\n");
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            channel = atoi((const char *)inputBuffer);
            if ((channel < 1) || (channel > channelCount))
            {
               printf("\n%s: %d is outside the limits[%d - %d]", "Channel #", channel, 1, channelCount);
            }
            break;
 
         default:
            break;
         }
      }
   } while (bQuit == FALSE);
}
 
static void Show_DSDemoFunc_Commands(void)
{
   int i;
   printf("\n\t\t DS Set Back-ground Test Demo Menu");
   printf("\n\t\t =================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < DS_FUNC_CMD_COUNT && DS_DemoFuncMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", DS_DemoFuncMenuCmds[i].cmdstr, DS_DemoFuncMenuCmds[i].menustr);
   printf("\n");
}
 
static void Show_SetAngle_UserInput_Commands(void)
{
   int i;
 
   printf("\n\t\t Set Angle User Inputs\n ");
   printf("\n\nCommands");
   for (i = 0; i < DS_USER_INPUT_COUNT && DS_DemoUserInputs[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", DS_DemoUserInputs[i].cmdstr, DS_DemoUserInputs[i].menustr);
   printf("\n");
}
 
static void DS_RunBitTestFunc(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t udUserInput;
   bool_t bYes = FALSE;
 
   printf("\n================================================================");
   printf("\nThis program allows the user to put the D/S module in different ");
   printf("\ntest modes.  The modes are: 1. On-line back ground test (D2).   ");
   printf("\n2. Off-line back ground test (D3).                              ");
   printf("\n1. Disable/Enable on-line back ground test (D2).");
   printf("\n2. Disable/Enable off-line back ground test (D3).");
   printf("\n3. Set test verify value.");
   printf("\n4. Set Angle");
   printf("\n5. Set Active Channel");
   printf("\n6. Set Module Power");
   printf("\n================================================================\n");
 
   do
   {
      DS_ShowSetAngleTestResult(cardIndex, module, channel);
      showCurrentModChan(module, channel);
      Show_SetAngle_UserInput_Commands();
      udUserInput = getUserInput();
      switch (udUserInput)
      {
      case DS_USER_INPUT_SET_ANGLE:
      case DS_USER_INPUT_SET_D2:
      case DS_USER_INPUT_SET_D3:
      case DS_USER_INPUT_SET_TEST_VERIFY:
      case DS_USER_INPUT_ACTIVE_CHAN:
      case DS_USER_INPUT_POWER:
         DS_DemoUserInputs[udUserInput].func(cardIndex, module, channel);
         break;
 
      case DS_USER_INPUT_QUIT:
         bYes = TRUE;
         break;
 
      case DS_USER_INPUT_REFRESH:
      case DS_USER_INVALID_INPUT:
         break;
      }
 
   } while (bYes == FALSE);
}
 
static void DS_ShowSetAngleTestResult(int32_t cardIndex, int32_t module, int32_t channel)
{
   float64_t dValue = 0.0;
   uint32_t  unValue = 0;
   uint8_t   u8Status[10];
   uint8_t   u8Value = 0;
 
   memset(u8Status, 0, sizeof(u8Status));
   printf("\nSet angle   Meas angle  D2          D3          Mode        Test Verify Meas. VLL   Meas. VRef  Meas.RFreq  Status      Act.Chan.   Power     \n");
   printf("\n                        Off/On      Off/On      Ratio/Fixed   Value                                         S/R/B/P                             ");
   printf("\n----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------\n");
   /*Set Angle*/
   check_status(naibrd_DS_GetAngle(cardIndex, module, channel, NAI_DS_ANGLE_SINGLE, &dValue));
   printf("%-12.4f", dValue);
   /*get measured angle*/
   check_status(naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_ANGLE, &dValue));
   printf("%-12.4f", dValue);
   /*Get D2 Test */
   check_status(naibrd_DS_GetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, &u8Value));
   if (u8Value == NAI_ENABLE)
      printf("%-12s", DS_ENABLE);
   else
      printf("%-12s", DS_DISABLE);
   /*Get D3 Test */
   check_status(naibrd_DS_GetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, &u8Value));
   if (u8Value == NAI_ENABLE)
      printf("%-12s", DS_ENABLE);
   else
      printf("%-12s", DS_DISABLE);
   /*fixed/ratio mode */
   check_status(naibrd_DS_GetRatioFixedMode(cardIndex, module, channel, &unValue));
   if ((nai_ds_output_ratio_fixed_mode_t)unValue == NAI_DS_OUTPUT_RATIO)
      printf("%-12s", DS_RATIO);      /*Ratio*/
   else
      printf("%-12s", DS_FIXED);      /*Fixed*/
  /*D2 Verify Value*/
   check_status(naibrd_DS_GetTestVerify(cardIndex, module, &unValue));
   printf("0x%-10x", unValue);
   /*measured Vll */
   check_status(naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_SIGNAL_VOLTAGE, &dValue));
   printf("%-12.4f", dValue);        /*meas Vll*/
   /*measured Vref */
   check_status(naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_REF_VOLTAGE, &dValue));
   printf("%-12.4f", dValue);        /*meas Vref*/
   /*measured RefFreq */
   check_status(naibrd_DS_GetMeasuredValue(cardIndex, module, channel, NAI_DS_MEASURED_REF_FREQUENCY, &dValue));
   printf("%-12.4f", dValue);        /*meas RefFreq*/
   /*get Status: S=Signal Loss, R=Reference Loss, B=BIT Loss, P=Phase Loss*/
   getStatus(cardIndex, module, channel, u8Status);
   printf("%-12s", u8Status);        /*status*/
   /*get Active Channel*/
   check_status(naibrd_DS_GetActiveChannel(cardIndex, module, channel, &u8Value));
   if (u8Value == NAI_ENABLE)
      printf("%-12s", DS_ENABLE);
   else
      printf("%-12s", DS_DISABLE);
   /*get power State*/
   check_status(naibrd_DS_GetPowerEnable(cardIndex, module, channel, &u8Value));
   if (u8Value == NAI_ENABLE)
      printf("%-12s", DS_ENABLE);
   else
      printf("%-12s", DS_DISABLE);
   printf("\n");
}
 
static void DS_SetNewAngle(int32_t cardIndex, int32_t module, int32_t channel)
{
   float64_t dValue = 0.0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   printf("\nEnter New Angle\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   dValue = atof((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_SET_ANGLE, dValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_SET_ANGLE, dValue);
   else
   {
      /*Set angle*/
      check_status(naibrd_DS_SetAngle(cardIndex, module, channel, NAI_DS_ANGLE_SINGLE, dValue));
   }
}
 
static void DS_SetD2Test(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t unValue = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   channel = 1;
   printf("\nOn-line Test (D2):[0=Disable, 1 =Enable]\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   unValue = atoi((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_SET_D2, unValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_SET_D2, unValue);
   else
   {
      if (unValue == NAI_ENABLE)
         check_status(naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, (uint8_t)NAI_ENABLE));
      else
         check_status(naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_ON_LINE_TEST, (uint8_t)NAI_DISABLE));
   }
}
 
static void DS_SetD3Test(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t unValue = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   channel = 1;
   printf("\nOff-line Test (D3):[0=Disable, 1 =Enable]\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   unValue = atoi((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_SET_D2, unValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_SET_D2, unValue);
   else
   {
      if (unValue == NAI_ENABLE)
         check_status(naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, (uint8_t)NAI_ENABLE));
      else
         check_status(naibrd_DS_SetTestModeEnable(cardIndex, module, NAI_DS_OFF_LINE_TEST, (uint8_t)NAI_DISABLE));
   }
}
 
static void DS_SetTestVerifyValue(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t unValue = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   channel = 1;
   printf("\nEnter Test Verify Value\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   unValue = atol((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_SET_TEST_VERIFY, unValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_SET_TEST_VERIFY, unValue);
   else
   {
      /*Set Test Verify*/
      check_status(naibrd_DS_SetTestVerify(cardIndex, module, unValue));
   }
}
 
static void DS_SetActiveChannel(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t unValue = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   printf("\nSet Active Channel [Disable = 0, Enable = 1]\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   unValue = atoi((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_ACTIVE_CHAN, unValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_ACTIVE_CHAN, unValue);
   else
   {
      /*Set active channel*/
      check_status(naibrd_DS_SetActiveChannel(cardIndex, module, channel, (uint8_t)unValue));
   }
}
 
static void DS_SetPower(int32_t cardIndex, int32_t module, int32_t channel)
{
   float64_t dValue = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   printf("\nSet Power[DISABLE = 0, ENABLE = 1]\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   dValue = atof((const char *)inputBuffer);
   bQuit = checkUserInput(DS_USER_INPUT_POWER, dValue);
   if (bQuit == TRUE)
      printInvalidUserInputMessage(DS_USER_INPUT_POWER, dValue);
   else
   {
      /*Power Enable*/
      check_status(naibrd_DS_SetPowerEnable(cardIndex, module, channel, (uint8_t)dValue));
   }
}
 
static uint32_t getUserInput()
{
   uint32_t unCmdNumber = 0;
   int8_t str1[80];
   int8_t str2[80];
   uint32_t udCommand = 0;
   int32_t x;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
 
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   for (unCmdNumber = 0; unCmdNumber < DS_USER_INPUT_COUNT && DS_DemoUserInputs[unCmdNumber].cmdstr != NULL; unCmdNumber++)
   {
      memset(str1, 0, sizeof(str1));
      memset(str2, 0, sizeof(str2));
      strncpy((char*)str1, (const char*)DS_DemoUserInputs[unCmdNumber].cmdstr, inputResponseCnt);
      strncpy((char*)str2, (const char*)inputBuffer, inputResponseCnt);
 
      for (x = 0; x < inputResponseCnt; x++)
      {
         str1[x] = (int8_t)toupper(str1[x]);
         str2[x] = (int8_t)toupper(str2[x]);
 
      }
      if (strncmp((const char*)str1, (const char*)str2, inputResponseCnt) == 0)
      {
         udCommand = unCmdNumber;
         break;
      }
   }
   return(udCommand);
}
 
static bool_t checkUserInput(uint32_t uTypeIdx, float64_t dUserInput)
{
   bool_t bValidInput = FALSE;
 
   if ((dUserInput > DS_Inputs_Limits[uTypeIdx].upperLimit) || (dUserInput < DS_Inputs_Limits[uTypeIdx].lowerLimit))
      bValidInput = TRUE;
   return(bValidInput);
}
 
static void printInvalidUserInputMessage(uint32_t uTypeIdx, float64_t dUserInput)
{
   printf("\n%s: %0.4f is outside the limits[%0.4f - %0.4f]", DS_Inputs_Limits[uTypeIdx].cmdstr, dUserInput, DS_Inputs_Limits[uTypeIdx].lowerLimit, DS_Inputs_Limits[uTypeIdx].upperLimit);
}
 
static void showCurrentModChan(int32_t nModule, int32_t nChannel)
{
   printf("\nModule  :%d", nModule);
   printf("\nChannel :%d", nChannel);
}
 
static void getStatus(int32_t cardIndex, int32_t module, int32_t channel, uint8_t *u8Status)
{
   uint32_t unSingalLoss = 0;
   uint32_t unRefLoss = 0;
   uint32_t unBitLoss = 0;
   uint32_t unPhaseLoss = 0;
 
   check_status(naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_SIGNAL_LOST, &unSingalLoss));
   check_status(naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_REFERENCE_LOST, &unRefLoss));
   check_status(naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_BIT_LOST, &unBitLoss));
   check_status(naibrd_DS_GetStatus(cardIndex, module, channel, NAI_DS_STATUS_LATCH_PHASE_LOST, &unPhaseLoss));
 
   /*SIG*/
   if ((nai_ds_module_status_t)unSingalLoss == NAI_DS_MODULE_STATUS_GOOD)
      *u8Status++ = DS_STATUS_GOOD[0];
   else
      *u8Status++ = DS_STATUS_BAD[0];
   *u8Status++ = SYM_SLASH[0];
 
   /*REF*/
   if ((nai_ds_module_status_t)unRefLoss == NAI_DS_MODULE_STATUS_GOOD)
      *u8Status++ = DS_STATUS_GOOD[0];
   else
      *u8Status++ = DS_STATUS_BAD[0];
   *u8Status++ = SYM_SLASH[0];
 
   /*BIT*/
   if ((nai_ds_module_status_t)unBitLoss == NAI_DS_MODULE_STATUS_GOOD)
      *u8Status++ = DS_STATUS_GOOD[0];
   else
      *u8Status++ = DS_STATUS_BAD[0];
   *u8Status++ = SYM_SLASH[0];
 
   /*PLL*/
   if ((nai_ds_module_status_t)unPhaseLoss == NAI_DS_MODULE_STATUS_GOOD)
      *u8Status++ = DS_STATUS_GOOD[0];
   else
      *u8Status++ = DS_STATUS_BAD[0];
}