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

RLY BasicOps

RLY BasicOps Sample Application (SSK 2.x)

Overview

The RLY BasicOps sample application demonstrates how to configure and operate relay (RLY) modules using the NAI Software Support Kit (SSK 2.x). It covers the core relay operations you will need in your own application: opening and closing individual relays, setting relay state words for bulk operations, reading relay position and BIT status, configuring interrupt enables and trigger modes, and toggling BIT status display.

This sample supports RY1 and RY2 relay modules. It also works with earlier-generation relay modules (KN, KL) with a reduced command set. Each menu command maps directly to one or more naibrd_RLY_*() API calls that you can lift into your own code.

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

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a relay module installed (RY1 or RY2).

  • SSK 2.x installed on your development host.

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

How to Run

Launch the rly_basic_ops executable from your build output directory. On startup the application looks for a configuration file (default_RLY_BasicOp.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, you select a channel and a command menu lets you exercise each relay 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 RLY.

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

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

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

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

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

#if defined (__VXWORKS__)
int32_t RLY_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = NAI_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) == NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  Run_RLY_BasicOps(cardIndex, module, moduleID);
               }
            }
         }

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

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

   return 0;
}

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

  • This sample uses the legacy __VXWORKS__ preprocessor guard. Most SSK 2.x samples use NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS.

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

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

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

Important

Common connection errors you may encounter at this stage:

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

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

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

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

Program Structure

Entry Point

On VxWorks the entry point is RLY_BasicOps(); on all other platforms it is main(). The preprocessor guard __VXWORKS__ selects between them. After board connection and module selection, the application calls Run_RLY_BasicOps() which validates the module and delegates to Cfg_RLY_Channel() for the interactive command loop.

Command Loop

Cfg_RLY_Channel() prompts the user for a channel number, displays the current relay status, and presents a menu of relay commands. The menu is dynamically constructed based on the module type — RY1 and RY2 modules get additional commands for clearing BIT status and setting interrupt trigger modes. Commands are defined in RLY_BasicOpMenuCmds[] and RLY_GEN5_MenuCmds[].

Command Description

Help

Display help notes with register references for the relay module.

Open

Open the relay on the selected channel (COM to N.C.).

CLOse

Close the relay on the selected channel (COM to N.O.).

Word

Set the relay state word to control all channels simultaneously.

ENable

Enable or disable BIT interrupt for the selected channel.

Status

Toggle the BIT status display on or off.

R (RY1/RY2 only)

Clear (reset) the latched BIT status for the selected channel.

EDge (RY1/RY2 only)

Select interrupt trigger type: Edge or Level.

Displaying Relay Status

The Display_RLY_Status() function reads and displays the relay setting, relay position, and BIT status for all channels. The relay position readback indicates whether the physical relay contacts match the commanded state. BIT status is displayed both as real-time and latched values.

static bool_t Display_RLY_Status(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
   nai_status_bit_t BITstatus = 0;
   uint32_t BITstatusWord = 0;
   nai_status_bit_t BITstatuslatched = 0;
   naibrd_rly_state_t relaysetting;
   naibrd_rly_state_t relayposition;
   int32_t MaxChannel;

   MaxChannel = naibrd_RLY_GetChannelCount(ModuleID);
   if (bShowBIT)
      check_status(naibrd_RLY_GetGroupRaw(cardIndex, module, 1,
         (naibrd_rly_raw_group_type_t)NAIBRD_RLY_RAW_GROUP_BIT_LATCHED_STATUS, &BITstatusWord));

   for (i = 0; i < MaxChannel; i++)
   {
      check_status(naibrd_RLY_GetRelayState(cardIndex, module, displaychan, &relaysetting));
      check_status(naibrd_RLY_GetRelayPosition(cardIndex, module, displaychan, &relayposition));
      if (bShowBIT)
         check_status(naibrd_RLY_GetChanMappedStatus(cardIndex, module, displaychan,
            NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_REALTIME, &BITstatus));
   }
   return NAI_FALSE;
}

Key API calls used:

  • naibrd_RLY_GetChannelCount() — returns the number of relay channels for the module.

  • naibrd_RLY_GetRelayState() — reads the commanded relay state (open or closed).

  • naibrd_RLY_GetRelayPosition() — reads the physical relay position readback.

  • naibrd_RLY_GetGroupRaw() — reads a raw group register (e.g., latched BIT status word).

  • naibrd_RLY_GetChanMappedStatus() — reads a per-channel status bit (real-time or latched).

Setting Relay State

Individual relays are opened or closed using naibrd_RLY_SetRelayState(). The Open and Close commands in the menu call this directly.

case RLY_BASICOP_CMD_OPEN:
   check_status(naibrd_RLY_SetRelayState(cardIndex, module, chan, NAIBRD_RLY_STATE_OPEN));
   break;
case RLY_BASICOP_CMD_CLOSE:
   check_status(naibrd_RLY_SetRelayState(cardIndex, module, chan, NAIBRD_RLY_STATE_CLOSE));
   break;
  • naibrd_RLY_SetRelayState() — sets the relay state for a channel. NAIBRD_RLY_STATE_OPEN connects COM to N.C.; NAIBRD_RLY_STATE_CLOSE connects COM to N.O.

Setting Relay State Word

The Configure_RLY_StateWord() function allows you to set all relay channels simultaneously using a bitmapped state word. Each bit position corresponds to a channel (LSB = channel 1).

static nai_status_t Configure_RLY_StateWord(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   uint32_t stateword = 0;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiif_printf("\r\nEnter the relay state word to set:  Range [0 to 15)\r\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit && inputResponseCnt > 0)
   {
      stateword = (atoi((const char *)inputBuffer)) & 0xF;
      check_status(naibrd_RLY_SetGroupRaw(cardIndex, module, 1,
         (naibrd_rly_raw_group_type_t)NAIBRD_RLY_RAW_GROUP_RELAYSTATE, stateword));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
  • naibrd_RLY_SetGroupRaw() — writes a raw value to a group register. Used here to set all relay states in one operation.

Configuring Interrupts

The application supports configuring BIT interrupt enable and trigger type for RY1/RY2 modules.

static nai_status_t Configure_RLY_Interrupt_Enable(int32_t paramCount, int32_t* p_params)
{
   // Prompts for Enable or Disable
   check_status(naibrd_RLY_SetChanMappedInterruptEnable(cardIndex, module, chan,
      NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_LATCHED, enable));
   return bQuit;
}

static nai_status_t Configure_RLY_Interrupt_Trigger(int32_t paramCount, int32_t* p_params)
{
   // Prompts for Edge or Level trigger
   check_status(naibrd_RLY_SetChanMappedInterruptTriggerType(cardIndex, module, chan,
      NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_LATCHED, trigmode));
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
  • naibrd_RLY_SetChanMappedInterruptEnable() — enables or disables the BIT interrupt for a channel.

  • naibrd_RLY_SetChanMappedInterruptTriggerType() — sets the interrupt trigger mode to edge (one-shot on transition) or level (continuous while active).

  • naibrd_RLY_ClearChanMappedStatus() — clears the latched BIT status for a channel (used by the R command on RY1/RY2).

Troubleshooting Reference

Error / Symptom Possible Causes Suggested Resolution

Module not recognized as RLY

The selected module slot does not contain a relay module.

Verify the module type in the slot. See the RY1-RY2 Manual.

Relay does not change state

The module may be in a fault condition or the relay may be physically stuck.

Check the BIT status for the channel. Verify wiring and relay health.

BIT status shows Nogo

The relay position readback does not match the commanded state.

This may indicate relay wear or a wiring issue. Clear the latched status and re-test.

State word has no effect

The entered value may be outside the valid range for the number of channels.

Ensure the state word value is within [0, 2^N - 1] where N is the number of relay channels.

Interrupt commands not available

The R (clear) and EDge (trigger type) commands only appear for RY1 and RY2 modules.

Earlier-generation modules (KN, KL) do not support these features.

Latched status does not clear

The underlying fault condition is still present.

Resolve the fault condition first, then clear the latched status.

Help shows different registers

The help display adapts its register references based on module type (RY1/RY2 vs. KN/KL).

This is expected behavior. Use the register references that match your module type.

Full Source

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

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

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

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

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

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

#define K6_VER_4 0x3420u /* "4 " */

/* Function prototypes */
static void Run_RLY_BasicOps(int32_t cardIndex, int32_t module, uint32_t modid);
static void Cfg_RLY_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
static bool_t Display_RLY_Status(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
static nai_status_t Configure_RLY_StateWord(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_RLY_Interrupt_Enable(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_RLY_Interrupt_Trigger(int32_t paramCount, int32_t* p_params);
static nai_status_t DisplayHelp(int32_t paramCount, int32_t* p_params);
bool_t bShowBIT = NAI_TRUE;

static const int32_t DEF_RLY_CHANNEL = 1;

/****** Command Table *******/
enum rly_basicops_commands
{
   RLY_BASICOP_CMD_HELP,
   RLY_BASICOP_CMD_OPEN,
   RLY_BASICOP_CMD_CLOSE,
   RLY_BASICOP_CMD_SETWORD,
   RLY_BASICOP_CMD_INTERRUPT_ENABLE,
   RLY_BASICOP_CMD_TOGGLE,
   RLY_BASICOP_CMD_CLEAR,              /* RY1/RY2 only */
   RLY_BASICOP_CMD_INTERRUPT_TRIG,     /* RY1/RY2 only */
   RLY_BASICOP_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t RLY_BasicOpMenuCmds[] = {
   {"Help",    "RLY Notes",                     RLY_BASICOP_CMD_HELP,               DisplayHelp},
   {"Open",    "RLY Open Relay",                RLY_BASICOP_CMD_OPEN,               NULL},
   {"CLOse",   "RLY Close Relay",               RLY_BASICOP_CMD_CLOSE,              NULL},
   {"Word",    "RLY Set Word",                  RLY_BASICOP_CMD_SETWORD,            Configure_RLY_StateWord},
   {"ENable",  "RLY Select Interrupt Enable",   RLY_BASICOP_CMD_INTERRUPT_ENABLE,   Configure_RLY_Interrupt_Enable},
   {"Status",  "RLY Toggle Status Display",     RLY_BASICOP_CMD_TOGGLE,             NULL}
};

naiapp_cmdtbl_params_t RLY_GEN5_MenuCmds[] = {
   {"R",    "RLY Reset BIT Status",              RLY_BASICOP_CMD_CLEAR,              NULL},
   {"EDge", "RLY Select Interrupt Trig",         RLY_BASICOP_CMD_INTERRUPT_TRIG,     Configure_RLY_Interrupt_Trigger}
};

/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t RLY_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = NAI_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) == NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  Run_RLY_BasicOps(cardIndex, module, moduleID);
               }
            }
         }

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

   naiif_printf("\r\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 Run_RLY_BasicOps(int32_t cardIndex, int32_t module, uint32_t modid)
{
   int32_t MaxChannel;

   MaxChannel = naibrd_RLY_GetChannelCount(modid);

   if (MaxChannel == 0)
      naiif_printf(" *** Module selection not recognized as RLY module. ***\r\n\r\n");
   else
      Cfg_RLY_Channel(cardIndex, module, modid, MaxChannel);
}

static void Cfg_RLY_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bContinue = NAI_TRUE;
   bool_t bCmdFound = NAI_FALSE;
   int32_t chan, defaultchan = 1;
   int32_t cmd;
   naiapp_cmdtbl_params_t menuCmds[RLY_BASICOP_CMD_COUNT];
   int32_t menuCnt, totalMenuCnt;
   int32_t i;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiapp_AppParameters_t  rly_basicops_params;
   p_naiapp_AppParameters_t rly_basicOps_params = &rly_basicops_params;
   rly_basicOps_params->cardIndex = cardIndex;
   rly_basicOps_params->module = module;
   rly_basicOps_params->channel = 1;
   rly_basicOps_params->maxChannels = naibrd_RLY_GetChannelCount(ModuleID);
   rly_basicOps_params->modId = ModuleID;
   rly_basicOps_params->displayHex = NAI_FALSE;

   while (bContinue)
   {
      naiif_printf("    \r\n\r\n");
      naiif_printf("Channel selection \r\n");
      naiif_printf("================= \r\n");
      defaultchan = DEF_RLY_CHANNEL;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);

      /* Update Menu Cmds based on Module ID */
      totalMenuCnt = 0;
      menuCnt = sizeof(RLY_BasicOpMenuCmds) / sizeof(naiapp_cmdtbl_params_t);
      for (i = 0; i < menuCnt; i++)
         menuCmds[totalMenuCnt++] = RLY_BasicOpMenuCmds[i];
      if ((ModuleID == NAIBRD_MODULE_ID_RY1) || (ModuleID == NAIBRD_MODULE_ID_RY2))
      {
         /* Added menu for Gen 5 Relay modules */
         menuCnt = sizeof(RLY_GEN5_MenuCmds) / sizeof(naiapp_cmdtbl_params_t);
         for (i = 0; i < menuCnt; i++)
            menuCmds[totalMenuCnt++] = RLY_GEN5_MenuCmds[i];
      }

      naiapp_utils_LoadParamMenuCommands(totalMenuCnt, menuCmds);
      while (bContinue)
      {
         Display_RLY_Status(cardIndex, module, chan, ModuleID);

         naiapp_display_ParamMenuCommands((int8_t *)"RLY Basic Operation Menu");
         naiif_printf("\r\n Type RLY command or %c to quit : ", NAI_QUIT_CHAR);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
               if (bCmdFound)
               {
                  naiif_printf("  <%s>", menuCmds[cmd].cmdstr);
                  switch (cmd)
                  {
                     case RLY_BASICOP_CMD_OPEN:
                        check_status(naibrd_RLY_SetRelayState(cardIndex, module, chan, NAIBRD_RLY_STATE_OPEN));
                        break;
                     case RLY_BASICOP_CMD_CLOSE:
                        check_status(naibrd_RLY_SetRelayState(cardIndex, module, chan, NAIBRD_RLY_STATE_CLOSE));
                        break;
                     case RLY_BASICOP_CMD_CLEAR:
                        check_status(naibrd_RLY_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_LATCHED));
                        break;
                     case RLY_BASICOP_CMD_TOGGLE:
                        bShowBIT = (~bShowBIT) & 0x1;
                        break;
                     case RLY_BASICOP_CMD_SETWORD:
                     case RLY_BASICOP_CMD_HELP:
                     case RLY_BASICOP_CMD_INTERRUPT_ENABLE:
                     case RLY_BASICOP_CMD_INTERRUPT_TRIG:
                        RLY_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)rly_basicOps_params);
                        break;
                     default:
                        naiif_printf("Invalid command entered\r\n");
                        break;
                  }
               }
               else
                  naiif_printf("Invalid command entered\r\n");
            }
         }
         else
            bContinue = NAI_FALSE;
      }
   }
}

static bool_t Display_RLY_Status(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
   nai_status_bit_t BITstatus = 0;
   uint32_t BITstatusWord = 0;
   nai_status_bit_t BITstatuslatched = 0;
   naibrd_rly_state_t relaysetting;
   naibrd_rly_state_t relayposition;
   int32_t MaxChannel;
   uint8_t i = 0;
   uint8_t displaychan = 0;
   naiif_printf("\r\n\r\n");
   naiif_printf("\r\n === Setting Channel %d ===\r\n\r\n", chan);
   MaxChannel = naibrd_RLY_GetChannelCount(ModuleID);
   if (bShowBIT)
   {
      naiif_printf("Chan   Relay Setting       Relay Position       BIT Status  Latched Status \r\n");
      naiif_printf("---- ------------------- -------------------- ------------ ---------------- \r\n");
   }
   else
   {
      naiif_printf("Chan   Relay Setting       Relay Position     \r\n");
      naiif_printf("---- ------------------- -------------------- \r\n");
   }
   if (bShowBIT)
      check_status(naibrd_RLY_GetGroupRaw(cardIndex, module, 1, (naibrd_rly_raw_group_type_t)NAIBRD_RLY_RAW_GROUP_BIT_LATCHED_STATUS, &BITstatusWord));
   for (i = 0; i < MaxChannel; i++)
   {
      displaychan = i + 1;
      naiif_printf(" %2d ", displaychan);

      check_status(naibrd_RLY_GetRelayState(cardIndex, module, displaychan, &relaysetting));
      if (relaysetting == 1)
      {
         naiif_printf("     Closed          ");
      }
      else
         naiif_printf("      Open           ");

      check_status(naibrd_RLY_GetRelayPosition(cardIndex, module, displaychan, &relayposition));
      if (relayposition == 1)
         naiif_printf(" Closed (COM - N.O.) ");
      else
         naiif_printf("  Open (COM - N.C.)  ");

      if (bShowBIT)
      {
         BITstatuslatched = (BITstatusWord >> (displaychan - 1)) & 0x1;
         check_status(naibrd_RLY_GetChanMappedStatus(cardIndex, module, displaychan, NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_REALTIME, &BITstatus));

         switch (BITstatus)
         {
            case 0:
               naiif_printf("    Go       ");
               break;
            case 1:
               naiif_printf("    Nogo     ");
               break;
            default:
               naiif_printf("  Unknown    ");
               break;
         }
         naiif_printf("   ");
         switch (BITstatuslatched)
         {
            case 0:
               naiif_printf("     Go         ");
               break;
            case 1:
               naiif_printf("     Nogo       ");
               break;
            default:
               naiif_printf("   Unknown        ");
               break;
         }
      }
      naiif_printf("\r\n");
   }
   return NAI_FALSE;
}

static nai_status_t Configure_RLY_StateWord(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bUpdateOutput = NAI_FALSE;
   uint32_t stateword = 0;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   naiif_printf("\r\nEnter the relay state word to set:  Range [0 to 15) \r\n Channel Bitmapped position, 1 energizes relay \r\n > ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         stateword = (atoi((const char *)inputBuffer)) & 0xF;
         bUpdateOutput = NAI_TRUE;
      }
   }
   if (!bQuit)
   {
      if (bUpdateOutput)
         check_status(naibrd_RLY_SetGroupRaw(cardIndex, module, 1, (naibrd_rly_raw_group_type_t)NAIBRD_RLY_RAW_GROUP_RELAYSTATE, stateword));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t Configure_RLY_Interrupt_Enable(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bUpdateOutput = NAI_FALSE;
   bool_t enable = 0;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   int32_t chan = p_ad_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   naiif_printf("\r\nEnter the selection for interrupt enable:  'Enable'  or 'Disable' \r\n > ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         switch (toupper(inputBuffer[0]))
         {
            case 'E':
               naiif_printf(" <Enable>\r\n\r\n");
               enable = 1;
               break;
            case 'D':
               naiif_printf(" <Disable>\r\n\r\n");
               enable = 0;
               break;
         }
         bUpdateOutput = NAI_TRUE;
      }
   }
   if (!bQuit)
   {
      if (bUpdateOutput)
         check_status(naibrd_RLY_SetChanMappedInterruptEnable(cardIndex, module, chan, NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_LATCHED, enable));
   }
   return bQuit;
}

static nai_status_t Configure_RLY_Interrupt_Trigger(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bUpdateOutput = NAI_FALSE;
   naibrd_int_trigger_type_t trigmode = 0;
   p_naiapp_AppParameters_t p_rly_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_rly_params->cardIndex;
   int32_t module = p_rly_params->module;
   int32_t chan = p_rly_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   naiif_printf("\r\nEnter the selection for interrupt triggering mode:  'Edge'  or 'Level' \r\n > ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         switch (toupper(inputBuffer[0]))
         {
            case 'E':
               naiif_printf(" <Edge>\r\n\r\n");
               trigmode = 0;
               break;
            case 'L':
               naiif_printf(" <Level>\r\n\r\n");
               trigmode = 1;
               break;
         }
         bUpdateOutput = NAI_TRUE;
      }
   }
   if (!bQuit)
   {
      if (bUpdateOutput)
         check_status(naibrd_RLY_SetChanMappedInterruptTriggerType(cardIndex, module, chan, NAIBRD_RLY_CHAN_MAPPED_STATUS_BIT_LATCHED, trigmode));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t DisplayHelp(int32_t paramCount, int32_t* p_params)
{
   uint32_t ModuleID;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;

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

   naibrd_GetModuleName(cardIndex, module, &ModuleID);
   naiif_printf("\r\n\r\n\r\n");
   naiif_printf(" ===================================================================\r\n");
   naiif_printf(" Relay module has Form C relays, single pole double throw (SPDT) \r\n");
   naiif_printf(" A BIT status indication shows a mismatch detected between   \r\n");
   naiif_printf(" the relay setting and the position readback.                \r\n");
   naiif_printf(" Latched status retains any transient BIT indications that may have occurred. \r\n\r\n");
   if ((ModuleID == NAIBRD_MODULE_ID_RY1) || (ModuleID == NAIBRD_MODULE_ID_RY2))
   {
      naiif_printf(" SET_POSITION           0x1000  Set Relay position   (1:N.C.- COM) LSB=Ch.1  \r\n");
      naiif_printf(" READ_POSITION          0x1018  Read Relay position  (1:N.C.- COM) LSB=Ch.1  \r\n");
      naiif_printf(" INDUCE_BIT             0x1004  Force BIT fail       (1:forced)    LSB=Ch.1  \r\n");
      naiif_printf(" RELAY TYPE             0x1008  Relay config (fixed) (1:Latching, 0:Nonlatching) \r\n");
      naiif_printf(" INTERRUPT_SELECT_EDGE  0x080C  Edge/Level interrupt (1:Level)    LSB=Ch.1  \r\n");
      naiif_printf(" INTERRUPT_ENABLE       0x0808  BIT Interrupt Enable (1:Enable)    LSB=Ch.1  \r\n");
      naiif_printf(" BIT_STATUS_LATCHED     0x0804  Latched BIT status   (1:fault)     LSB=Ch.1  \r\n");
      naiif_printf(" BIT_STATUS_REALTIME    0x0800  Realtime BIT status  (1:fault)     LSB=Ch.1  \r\n");
   }
   else
   {
      naiif_printf(" NAI_REG_RLY_SET_POSITION                            0x000 \r\n");
      naiif_printf(" NAI_REG_RLY_READ_POSITION                           0x002 \r\n");
      naiif_printf(" NAI_REG_RLY_BIT_STATUS                              0x0D0  Same as latched status on KN/KL\r\n");
      naiif_printf(" NAI_REG_RLY_BIT_STATUS_LATCHED                      0x0D0 \r\n");
      naiif_printf(" NAI_REG_RLY_INDUCE_BIT                              0x0D2 \r\n");
      naiif_printf(" NAI_REG_RLY_BIT_INT_ENAB                            0x0E8 \r\n");
      naiif_printf(" NAI_REG_RLY_INT_VECTOR_BIT                          0x3E0 \r\n");
   }
   return NAI_SUCCESS;
}

Help Bot

X