REF BasicOps
Edit this on GitLab
REF BasicOps Sample Application (SSK 1.x)
Overview
The REF BasicOps sample application demonstrates how to configure and control AC reference signal generation using the NAI Software Support Kit (SSK 1.x). AC reference modules produce precision sinusoidal excitation signals that drive synchro, resolver, and LVDT position sensors. Without a stable, accurately controlled reference signal, these sensors cannot produce meaningful position data — the reference is the "carrier" that the sensor modulates, and the measurement system demodulates the return signal against it to extract angle or displacement. Getting the reference voltage, frequency, and power state right is a prerequisite for any synchro/resolver or LVDT measurement chain.
This sample covers the core REF operations you will need in your own application: setting output frequency and voltage, enabling and disabling channel output power, reading back measured voltage and current, monitoring overcurrent status, resetting fault conditions, and managing a hardware watchdog timer. Each menu command maps directly to one or more naibrd_REF_*() API calls that you can lift into your own code.
This sample supports the following REF module types defined in naibrd_ref.h: AC1, AC2, AC3, AC4, W1 through W7, LD6, and SDP. The specific voltage and frequency ranges available depend on which module variant is installed — consult your module’s manual for hardware-specific limits.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a REF module installed (AC1-AC4, W1-W7, LD6, or SDP).
-
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 REF_BasicOps executable from your build output directory. On startup the application looks for a configuration file (default_RefBasicOps.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 the application presents a command menu for exercising each REF 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 REF. For details on board connection configuration, see the First Time Setup Guide. |
The main() function follows a standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_RefBasicOps.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()so downstream code can adapt to the specific REF variant installed.
#if defined (__VXWORKS__)
int32_t REF_RunBasicOpsProgramSample(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))
{
REFBasicMenu_Run(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;
}
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Once connected to a board and module, the application initializes a parameter structure and enters the command loop. The menu system is a sample convenience — in your own code, call the naibrd_REF_*() API functions directly without the menu scaffolding.
Application Parameters
The sample packs the active card index, module number, module ID, channel count, and selected channel into an naiapp_AppParameters_t struct. Your application will need to track the same values: cardIndex identifies which board you are talking to, module identifies the slot, and channel identifies which REF output you are configuring.
naiapp_AppParameters_t ref_basicops_params;
p_naiapp_AppParameters_t ref_basicOps_params = &ref_basicops_params;
ref_basicOps_params->cardIndex = cardIndex;
ref_basicOps_params->module = module;
ref_basicOps_params->modId = modid;
ref_basicOps_params->maxChannels = naibrd_REF_GetChannelCount(modid);
ref_basicOps_params->displayHex = FALSE;
The call to naibrd_REF_GetChannelCount() returns the number of reference output channels available on the installed module variant. This value determines the valid channel range for all subsequent API calls.
Command Loop and Menu
The command loop displays current measurements for all channels, shows the available commands, and waits for user input. The available commands are:
| Command | Description |
|---|---|
|
Set the output frequency for the selected channel |
|
Set the output voltage for the selected channel |
|
Set channel control (enable/disable) |
|
Set output power on or off |
|
Reset channel fault conditions |
|
Open the watchdog timer submenu |
Displaying Channel Measurements
Before each command prompt, the sample reads back the current state of every channel on the module. This gives you real-time feedback on the reference signal being generated. The display shows frequency, measured voltage, measured current, output enable state, and overcurrent status.
To read these values in your own application, use the following API calls:
/* Read the configured frequency */
naibrd_REF_GetValueEx(cardIndex, module, channel, NAI_REF_FREQUENCY, &frequencyOut);
/* Read the measured output voltage and current */
naibrd_REF_GetMeasuredValueEx(cardIndex, module, channel, NAI_REF_MEASURED_VOLTAGE, &voltageOut);
naibrd_REF_GetMeasuredValueEx(cardIndex, module, channel, NAI_REF_MEASURED_CURRENT, ¤tOut);
/* Read whether the channel output is enabled */
naibrd_REF_GetChannelEnable(cardIndex, module, channel, &powerControlOut);
/* Check for an overcurrent condition on the module */
naibrd_REF_GetOverCurrentStatus(cardIndex, module, &overCurrent);
naibrd_REF_GetValueEx() retrieves a configured parameter (here, frequency), while naibrd_REF_GetMeasuredValueEx() retrieves the actual measured output. The distinction matters: the configured value is what you asked the module to produce; the measured value is what the hardware is actually delivering. A significant discrepancy between the two can indicate a wiring issue, an overcurrent condition, or a load problem.
naibrd_REF_GetOverCurrentStatus() is a module-level status (not per-channel). When it returns TRUE, at least one channel on the module has exceeded its current limit. You should check this status periodically and take corrective action — an overcurrent condition typically means the connected sensor load is too heavy or there is a short on the output.
|
Important
|
Common Errors
|
Setting Output Frequency
AC reference modules generate a sinusoidal excitation signal at a specific frequency. Synchro/resolver systems typically operate at 400 Hz or 47-1000 Hz depending on the application, while LVDT systems may use frequencies from 47 Hz up to 10 kHz. The frequency you configure must match the excitation frequency expected by the connected sensor.
To set the output frequency for a channel in your own application, call naibrd_REF_SetValueEx() with the NAI_REF_FREQUENCY parameter:
float64_t freq = 400.0; /* Frequency in Hz */
check_status(naibrd_REF_SetValueEx(cardIndex, module, channel, NAI_REF_FREQUENCY, freq));
The cardIndex, module, and channel parameters identify which output to configure. The freq value is specified in Hertz. Consult your module’s manual for the valid frequency range — it varies by module variant (for example, some modules support 47-10000 Hz while others have a narrower range).
|
Important
|
Common Errors
|
Setting Output Voltage
The output voltage determines the amplitude of the AC reference signal (typically specified as Vrms). Synchro systems commonly use 26 Vrms or 115 Vrms reference signals, while LVDT excitation voltages vary widely depending on the sensor. Setting the correct voltage is critical — too low and the sensor output will be weak and noisy; too high and you risk damaging the sensor or triggering an overcurrent fault.
To set the output voltage for a channel, call naibrd_REF_SetValueEx() with the NAI_REF_VOLTAGE parameter:
float64_t volt = 26.0; /* Voltage in Vrms */
check_status(naibrd_REF_SetValueEx(cardIndex, module, channel, NAI_REF_VOLTAGE, volt));
Consult your module’s manual for the valid voltage range and resolution. After setting the voltage, read it back with naibrd_REF_GetMeasuredValueEx() using NAI_REF_MEASURED_VOLTAGE to confirm the output has settled to the expected level.
|
Important
|
Common Errors
|
Setting Channel Control
The channel control function enables or disables signal generation on a per-channel basis. When a channel is disabled, no AC signal is generated on that output regardless of the configured voltage and frequency settings. This is useful for selectively activating reference outputs when your system has multiple sensors but you only need to excite certain ones at a given time.
To enable or disable a channel in your own application, call naibrd_REF_SetChannelEnable():
uint32_t channelControl = 1; /* 1 = enable, 0 = disable */
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, channelControl));
The channelControl parameter accepts 1 to enable the channel output or 0 to disable it.
|
Important
|
Common Errors
|
Setting Output Power
The output power command provides a direct on/off control for the channel’s output stage. This is functionally similar to channel control but provides an explicit binary toggle. In the sample, the user enters 0 for off or 1 for on:
/* Turn output power ON */
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, 1));
/* Turn output power OFF */
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, 0));
When you turn off output power, the module stops driving the reference signal on that channel. The configured voltage and frequency settings are preserved — when you re-enable power, the channel resumes generating the previously configured signal without needing to reconfigure it.
|
Important
|
Common Errors
|
Resetting Channel Faults
When an overcurrent or voltage fault occurs, the module latches the fault condition. The channel reset command clears these latches so the channel can resume normal operation. The sample resets both the overcurrent and voltage fault latches:
check_status(naibrd_REF_SetReset(cardIndex, module, channel, NAI_REF_RESET_OVERCURRENT));
check_status(naibrd_REF_SetReset(cardIndex, module, channel, NAI_REF_RESET_VOLTAGE));
Call naibrd_REF_SetReset() with NAI_REF_RESET_OVERCURRENT to clear the overcurrent fault latch, and with NAI_REF_RESET_VOLTAGE to clear the voltage fault latch. You should resolve the underlying cause of the fault (for example, removing a short circuit or reducing the load) before resetting — otherwise the fault will immediately re-trigger.
|
Important
|
Common Errors
|
Watchdog Operations
The watchdog timer is a hardware safety mechanism that monitors whether your application is still actively communicating with the REF module. When enabled, the watchdog expects periodic "strobe" signals from your software. If the strobe stops (because your application has crashed, hung, or lost communication), the watchdog triggers a fault and the module disables all outputs. This prevents an uncontrolled reference signal from continuing to drive sensors when the supervising software is no longer functioning.
The watchdog is essential in safety-critical applications where an unattended reference output could cause downstream measurement systems to report stale or incorrect position data. By shutting down the reference when software supervision is lost, the watchdog ensures a fail-safe state.
The watchdog submenu (WDT from the main menu) provides the following commands:
| Command | Description |
|---|---|
|
Set the watchdog quiet time (initial grace period) |
|
Set the watchdog window time (strobe deadline) |
|
Start a background thread that continuously strobes the watchdog |
|
Stop the watchdog strobing thread |
|
Return to the main menu |
Watchdog Timing: Quiet Time and Window Time
The watchdog uses a two-phase timing model:
-
Quiet time — an initial grace period after the watchdog is armed. During this interval, the watchdog ignores the absence of strobes, giving your application time to finish initialization before the watchdog becomes active. Set this with
naibrd_REF_SetWatchdogQuietTime(). -
Window time — once the quiet time expires, the watchdog expects a strobe within each window interval. If no strobe arrives before the window expires, the watchdog triggers a fault. Set this with
naibrd_REF_SetWatchdogWindow().
To configure these timers in your own application:
/* Set quiet time -- value is in microseconds, so multiply ms by 1000 */
uint32_t quietTimeMs = 1000; /* 1000 ms */
check_status(naibrd_REF_SetWatchdogQuietTime(cardIndex, module, quietTimeMs * 1000));
/* Set window time -- value is in microseconds, so multiply ms by 1000 */
uint32_t windowTimeMs = 500; /* 500 ms */
check_status(naibrd_REF_SetWatchdogWindow(cardIndex, module, windowTimeMs * 1000));
Both API calls accept the time value in microseconds. The sample converts from milliseconds by multiplying by 1000. For reliable operation with the sample’s strobe thread, set both quiet time and window time to at least 500 ms. Shorter intervals may not leave enough margin for thread scheduling latency.
Reading Watchdog Status
The watchdog display function reads back the current quiet time, window time, and watchdog fault status:
uint32_t quietTime = 0u, windowTime = 0u;
uint32_t wdStatLatched = 0u, wdStatRT = 0u;
check_status(naibrd_REF_GetWatchdogQuietTime(cardIndex, module, &quietTime));
check_status(naibrd_REF_GetWatchdogWindow(cardIndex, module, &windowTime));
check_status(naibrd_REF_GetChannelStatus(cardIndex, module, chan,
NAI_REF_STATUS_WATCHDOG_TIMER_FAULT, NAI_REF_STATUS_REALTIME, &wdStatRT));
check_status(naibrd_REF_GetChannelStatus(cardIndex, module, chan,
NAI_REF_STATUS_WATCHDOG_TIMER_FAULT, NAI_REF_STATUS_LATCHED, &wdStatLatched));
The status is reported as both real-time and latched values. The real-time status indicates whether the watchdog fault is currently active. The latched status indicates whether a watchdog fault has occurred since the last reset — even if the fault has since cleared, the latch remains set until you explicitly reset it.
Strobing the Watchdog
Once the watchdog is configured, your application must periodically call naibrd_REF_WatchdogStrobe() to prevent the watchdog from triggering. The sample spawns a background thread that strobes at an interval of quietTime + (windowTime / 2), which places each strobe roughly in the middle of the window period:
check_status(naibrd_REF_GetWatchdogQuietTime(cardIndex, module, &quietTime));
check_status(naibrd_REF_GetWatchdogWindow(cardIndex, module, &windowTime));
quietTime = quietTime / 1000; /* Convert from microseconds to milliseconds */
windowTime = windowTime / 1000;
delayTime = quietTime + (windowTime / 2);
check_status(naibrd_REF_WatchdogStrobe(cardIndex, module));
do
{
nai_msDelay(delayTime);
check_status(naibrd_REF_WatchdogStrobe(cardIndex, module));
} while (!terminateThread);
In your own application, you do not need to use a separate thread — you can call naibrd_REF_WatchdogStrobe() from your main loop or any periodic task, as long as the interval between strobes does not exceed the window time.
|
Warning
|
When the strobe thread or application exits without disabling the watchdog, the module will shut off all outputs and will need to be power cycled to become operational again. Always kill the strobe thread cleanly before exiting. |
Stopping the Strobe Thread
The KILL command sets the terminateThread flag, which causes the strobe loop to exit on its next iteration. In your own application, ensure that you stop the watchdog strobe gracefully before shutting down:
naiapp_kill_WDStrobe_Thread();
|
Important
|
Common Errors
|
Troubleshooting Reference
The following table summarizes errors covered in the preceding sections. Consult your module’s manual for hardware-specific diagnostics.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Board not powered, not connected, or configuration file has wrong interface/address |
Verify power, cabling, and connection settings in the configuration file |
Connection timeout |
Network misconfiguration, firewall blocking, IP mismatch, or incorrect bus settings |
Confirm Ethernet IP settings or PCI/PCIe bus configuration; check firewall rules |
Invalid card or module index |
Wrong index values (cards are zero-based, modules are one-based) |
Verify hardware setup and adjust index values accordingly |
Module not present at selected slot |
The selected slot does not contain a REF module |
Use the board menu to identify populated slots |
Measured voltage reads zero |
Channel output power not enabled, or overcurrent fault active |
Enable channel power; check and clear overcurrent faults |
Measured voltage does not match configured voltage |
Sensor load too heavy, wiring issue, or overcurrent condition |
Check load impedance against module specs; inspect wiring; clear faults |
|
Frequency or voltage outside the module’s supported range |
Consult your module’s manual for valid parameter ranges |
|
Channel number exceeds the module’s channel count |
Call |
|
The installed module variant does not support the requested feature |
Consult your module’s manual for feature availability |
Fault re-latches immediately after reset |
Underlying fault condition (short, overload) still present |
Resolve the hardware issue before resetting the fault latch |
Module shuts off all outputs unexpectedly |
Watchdog timer expired due to missed strobes |
Ensure your application strobes the watchdog within the configured window time |
Module requires power cycle after watchdog fault |
Expected behavior — watchdog shutdown is not recoverable without power cycle |
Power cycle the module and reconfigure the watchdog with appropriate timing |
Watchdog strobe thread fails to start |
System resource limits, leaked thread handle, or OS-specific threading error |
Check system resources; ensure previous thread was properly terminated |
Full Source
Full Source — REF_BasicOps.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.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 "REF_Common.h"
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ref.h"
#include "advanced/nai_ether_adv.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_RefBasicOps.txt";
/* Function prototypes */
static bool_t REFBasicMenu_Run(int32_t cardIndex, int32_t module, uint32_t modid);
static bool_t REFBasicMenu_DisplayMeasurements(int32_t cardIndex, int32_t module, int32_t modid);
static nai_status_t REFBasicMenu_SetFrequency(int32_t paramCount, int32_t* p_params);
static nai_status_t REFBasicMenu_SetVoltage(int32_t paramCount, int32_t* p_params);
static nai_status_t REFBasicMenu_SetChannelControl(int32_t paramCount, int32_t* p_params);
static nai_status_t REFBasicMenu_SetOutputPower(int32_t paramCount, int32_t* p_params);
static nai_status_t REFBasicMenu_SetChannelReset(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_REF_WatchdogShowMenu(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_REF_WatchDogQuietTime(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_REF_WatchDogWindowTime(int32_t paramCount, int32_t* p_params);
static bool_t Handle_REF_DisplayWatchdog(int32_t cardIndex, int32_t module, int32_t chan);
static nai_status_t Handle_REF_StrobeWatchdog(int32_t paramCount, int32_t* p_params);
static nai_status_t Handle_REF_kill_WDStrobe_Thread(int32_t paramCount, int32_t* p_params);
static void naiapp_kill_WDStrobe_Thread();
static const int8_t *SAMPLE_WD_PGM_NAME = (const int8_t*)"REF Watchdog Operations";
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
enum ref_basicOpsMenu_commands
{
REF_BASICMENU_SET_FREQUENCY,
REF_BASICMENU_SET_VOLTAGE,
REF_BASICMENU_SET_CHANNEL_CONTROL,
REF_BASICMENU_SET_OUTPUT_POWER,
REF_BASICMENU_SET_CHANNEL_RESET,
REF_BASICOP_CMD_WATCHDOG_MENU,
REF_BASICMENU_CMD_COUNT
};
enum ref_watchdog_commands
{
REF_WD_CMD_QUIETTIME,
REF_WD_CMD_WINDOWTIME,
REF_WD_CMD_STROBE,
REF_WD_CMD_KILL,
REF_WD_CMD_BACK,
REF_WD_CMD_COUNT
};
naiapp_cmdtbl_params_t REF_BasicOpMenuCmds[] =
{
{ "FREQ", "Set Frequency", REF_BASICMENU_SET_FREQUENCY, REFBasicMenu_SetFrequency },
{ "VOLT", "Set Voltage", REF_BASICMENU_SET_VOLTAGE, REFBasicMenu_SetVoltage },
{ "CHAN", "Set Channel Control", REF_BASICMENU_SET_CHANNEL_CONTROL, REFBasicMenu_SetChannelControl },
{ "POWR", "Set Output Power", REF_BASICMENU_SET_OUTPUT_POWER, REFBasicMenu_SetOutputPower },
{"WDT", "Show Watchdog Menu Options", REF_BASICOP_CMD_WATCHDOG_MENU, Handle_REF_WatchdogShowMenu},
{ "REST", "ResetChannel", REF_BASICMENU_SET_CHANNEL_RESET, REFBasicMenu_SetChannelReset }
};
naiapp_cmdtbl_params_t REF_WatchdogOpMenuCmds[REF_WD_CMD_COUNT] =
{
{"BACK", "Back to Main Menu", REF_WD_CMD_BACK, NULL},
{"TIME QUIET", "Set Watchdog Quiet Time", REF_WD_CMD_QUIETTIME, Handle_REF_WatchDogQuietTime},
{"WINDOW", "Set Watchdog Window Time", REF_WD_CMD_WINDOWTIME, Handle_REF_WatchDogWindowTime},
{"STROBE", "Start thread to continuously strobe watchdog", REF_WD_CMD_STROBE, Handle_REF_StrobeWatchdog},
{"KILL", "Kill Watchdog strobing thread", REF_WD_CMD_KILL, Handle_REF_kill_WDStrobe_Thread}
};
#if defined (__VXWORKS__)
int32_t REF_RunBasicOpsProgramSample(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))
{
REFBasicMenu_Run(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;
}
static bool_t REFBasicMenu_Run(int32_t cardIndex, int32_t module, uint32_t modid)
{
bool_t bQuit = FALSE, bCmdFound;
int32_t cmd;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiapp_AppParameters_t ref_basicops_params;
p_naiapp_AppParameters_t ref_basicOps_params = &ref_basicops_params;
ref_basicOps_params->cardIndex = cardIndex;
ref_basicOps_params->module = module;
ref_basicOps_params->modId = modid;
ref_basicOps_params->maxChannels = naibrd_REF_GetChannelCount(modid);
ref_basicOps_params->displayHex = FALSE;
bQuit = naiapp_query_ChannelNumber(ref_basicOps_params->maxChannels, 1, &ref_basicOps_params->channel);
naiapp_utils_LoadParamMenuCommands(REF_BASICMENU_CMD_COUNT, REF_BasicOpMenuCmds);
do
{
REFBasicMenu_DisplayMeasurements(cardIndex, module, modid);
naiapp_display_ParamMenuCommands((int8_t*)"MENU_TITLE");
printf("\n Type command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit && inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case REF_BASICMENU_SET_FREQUENCY:
case REF_BASICMENU_SET_VOLTAGE:
case REF_BASICMENU_SET_CHANNEL_CONTROL:
case REF_BASICMENU_SET_OUTPUT_POWER:
case REF_BASICMENU_SET_CHANNEL_RESET:
case REF_BASICOP_CMD_WATCHDOG_MENU:
REF_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)ref_basicOps_params);
break;
default:
continue;
break;
}
}
else printf("Invalid command entered\n");
}
} while (!bQuit);
return TRUE;
}
static bool_t REFBasicMenu_DisplayMeasurements(int32_t cardIndex, int32_t module, int32_t modid)
{
int32_t channel, MAX_CHANNEL = naibrd_REF_GetChannelCount((uint32_t)modid);
float64_t frequencyOut = 0, voltageOut = 0, currentOut = 0;
uint32_t powerControlOut = 0;
bool_t overCurrent = FALSE;
printf("\n\n ================================================== \n");
printf("%7s%11s%9s%9s%8s%13s\n", "Chan", "Frequency", "Voltage", "Current", "Output", "OverCurrent");
for (channel = 1; channel <= MAX_CHANNEL; channel++)
{
naibrd_REF_GetValueEx(cardIndex, module, channel, NAI_REF_FREQUENCY, &frequencyOut);
naibrd_REF_GetMeasuredValueEx(cardIndex, module, channel, NAI_REF_MEASURED_VOLTAGE, &voltageOut);
naibrd_REF_GetMeasuredValueEx(cardIndex, module, channel, NAI_REF_MEASURED_CURRENT, ¤tOut);
naibrd_REF_GetChannelEnable(cardIndex, module, channel, &powerControlOut);
naibrd_REF_GetOverCurrentStatus(cardIndex, module, &overCurrent);
printf("%4d%13.3f%10.3f%8.3f", channel, frequencyOut, voltageOut, currentOut);
if (powerControlOut == TRUE)
printf("%5s", "ON");
else
printf("%6s", "OFF");
if (overCurrent == TRUE)
printf("%10s\n", "TRUE");
else
printf("%11s\n", "FALSE");
}
return TRUE;
}
static nai_status_t REFBasicMenu_SetFrequency(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
float64_t freq = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
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 channel = p_ad_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("Enter a frequency: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
freq = atoi((const char *)inputBuffer);
check_status(naibrd_REF_SetValueEx(cardIndex, module, channel, NAI_REF_FREQUENCY, freq));
}
return NAI_SUCCESS;
}
static nai_status_t REFBasicMenu_SetVoltage(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
float64_t volt = 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 channel = p_ad_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("Enter a voltage: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
volt = atoi((const char *)inputBuffer);
check_status(naibrd_REF_SetValueEx(cardIndex, module, channel, NAI_REF_VOLTAGE, volt));
}
return NAI_SUCCESS;
}
static nai_status_t REFBasicMenu_SetChannelControl(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t channelControl = 0;
p_naiapp_AppParameters_t p_ref_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ref_params->cardIndex;
int32_t module = p_ref_params->module;
int32_t channel = p_ref_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("Enter Channel Control: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
channelControl = atoi((const char *)inputBuffer);
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, channelControl));
}
return NAI_SUCCESS;
}
static nai_status_t REFBasicMenu_SetOutputPower(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ad_params->cardIndex;
int32_t module = p_ad_params->module;
int32_t channel = p_ad_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("Enter a Output Power (0 Off 1 On): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputBuffer[0] == '0')
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, 0));
else if (inputBuffer[0] == '1')
check_status(naibrd_REF_SetChannelEnable(cardIndex, module, channel, 1));
}
return NAI_SUCCESS;
}
static nai_status_t REFBasicMenu_SetChannelReset(int32_t paramCount, int32_t* p_params)
{
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 channel = p_ad_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_REF_SetReset(cardIndex, module, channel, NAI_REF_RESET_OVERCURRENT));
check_status(naibrd_REF_SetReset(cardIndex, module, channel, NAI_REF_RESET_VOLTAGE));
return NAI_SUCCESS;
}
static nai_status_t Handle_REF_WatchdogShowMenu(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
bool_t bCmdFound = FALSE;
int32_t cmd = 0;
int32_t numMenuCmds = 0;
p_naiapp_AppParameters_t p_ref_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ref_params->cardIndex;
int32_t module = p_ref_params->module;
int32_t chan = p_ref_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
numMenuCmds = REF_WD_CMD_COUNT;
naiapp_utils_LoadParamMenuCommands(numMenuCmds, REF_WatchdogOpMenuCmds);
while (bContinue)
{
Handle_REF_DisplayWatchdog(cardIndex, module, chan);
naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_WD_PGM_NAME);
printf("\nType REF 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)
{
REF_WatchdogOpMenuCmds[cmd].func(paramCount, p_params);
}
else
{
printf("\nInvalid command entered\n");
}
}
}
}
else
bContinue = FALSE;
}
numMenuCmds = REF_BASICMENU_CMD_COUNT;
naiapp_utils_LoadParamMenuCommands(numMenuCmds, REF_BasicOpMenuCmds);
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
static nai_status_t Handle_REF_WatchDogQuietTime(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t quietTime = 0u;
p_naiapp_AppParameters_t p_ref_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ref_params->cardIndex;
int32_t module = p_ref_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_REF_SetWatchdogQuietTime(cardIndex, module, quietTime * 1000));
}
else
{
printf("\nInvalid value entered\n");
}
}
else
{
check_status(naibrd_REF_SetWatchdogQuietTime(cardIndex, module, quietTime * 1000));
}
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
static nai_status_t Handle_REF_WatchDogWindowTime(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t windowTime = 0u;
p_naiapp_AppParameters_t p_ref_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ref_params->cardIndex;
int32_t module = p_ref_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_REF_SetWatchdogWindow(cardIndex, module, windowTime * 1000));
}
else
{
printf("\nInvalid value entered\n");
}
}
else
{
check_status(naibrd_REF_SetWatchdogWindow(cardIndex, module, windowTime * 1000));
}
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
static bool_t Handle_REF_DisplayWatchdog(int32_t cardIndex, int32_t module, int32_t chan)
{
uint32_t wdStatLatched = 0u;
uint32_t wdStatRT = 0u;
uint32_t windowTime = 0u;
uint32_t quietTime = 0u;
printf("\n\nREF Watchdog Data:\n");
check_status(naibrd_REF_GetWatchdogQuietTime(cardIndex, module, &quietTime));
quietTime = quietTime / 1000;
printf("Quiet Time: %d mS\n", quietTime);
check_status(naibrd_REF_GetWatchdogWindow(cardIndex, module, &windowTime));
windowTime = windowTime / 1000;
printf("Window Time: %d mS\n", windowTime);
check_status(naibrd_REF_GetChannelStatus(cardIndex, module, chan, NAI_REF_STATUS_WATCHDOG_TIMER_FAULT, NAI_REF_STATUS_LATCHED, &wdStatLatched));
check_status(naibrd_REF_GetChannelStatus(cardIndex, module, chan, NAI_REF_STATUS_WATCHDOG_TIMER_FAULT, NAI_REF_STATUS_REALTIME, &wdStatRT));
printf("WatchDog Status (R/L): (%d/%d)\n", wdStatRT, wdStatLatched);
printf("\n");
return TRUE;
}
static nai_status_t Handle_REF_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_ref_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ref_params->cardIndex;
int32_t module = p_ref_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;
}
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);
}
#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
}
#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_REF_GetWatchdogQuietTime(cardIndex, module, &quietTime));
check_status(naibrd_REF_GetWatchdogWindow(cardIndex, module, &windowTime));
quietTime = quietTime / 1000;
windowTime = windowTime / 1000;
delayTime = quietTime + (windowTime / 2);
check_status(naibrd_REF_WatchdogStrobe(cardIndex, module));
do
{
nai_msDelay(delayTime);
check_status(naibrd_REF_WatchdogStrobe(cardIndex, module));
} while (!terminateThread);
return NAI_SUCCESS;
}
static nai_status_t Handle_REF_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;
}