DIF Measure
Edit this on GitLab
DIF Measure Sample Application (SSK 1.x)
Overview
This sample application demonstrates how to use the enhanced FIFO-based measurement modes on DIF (Differential Input Function) channels using the NAI Software Support Kit (SSK 1.x). It serves as a practical API reference for building your own digital signal measurement and timing analysis functionality with NAI hardware.
While the DIF BasicOps sample covers standard digital I/O — reading input states, setting output values, configuring thresholds — this application goes further into the hardware’s measurement engine. DIF modules include dedicated measurement hardware that can autonomously capture timing characteristics of incoming digital signals without continuous host polling. The FPGA on the module watches each channel’s input, detects signal edges, and records timing data into a per-channel FIFO buffer. Your application then reads those FIFO entries to extract pulse widths, periods, frequencies, edge timestamps, or edge counts.
This is fundamentally different from basic I/O. With basic I/O, you poll a channel and get its current high/low state at that instant. With FIFO-based measurement, the hardware continuously monitors the signal and records every transition or timing event into the FIFO as it happens. You read the accumulated results later. This means you can capture signal characteristics that would be impossible to measure by polling — sub-microsecond pulse widths, precise edge-to-edge timing, and accurate frequency counts over defined intervals.
The application supports ten measurement modes, grouped into three categories:
-
Timing modes (modes 1-2, 9) — the hardware measures durations: how long the signal stays high, how long it stays low, or the full period between rising edges. Each measurement is stored as a FIFO entry in hardware time units.
-
Timestamp modes (modes 3-5) — the hardware records the exact time at which each rising edge, falling edge, or any edge occurs. The FIFO fills with a sequence of timestamps, giving you a complete record of when every transition happened.
-
Counting modes (modes 6-8) — the hardware counts rising edges, falling edges, or all edges. The count accumulates in a dedicated register rather than the FIFO. Mode 10 (interval counting) extends this by gating the count over a user-defined time window, effectively measuring frequency.
Supported modules: D8, DF1, DF2, DF3, CMH
Related samples:
-
DIF BasicOps Sample Application — standard digital I/O: read inputs, set outputs, configure thresholds and voltage levels
-
DIF PWM Sample Application — generate PWM output signals on DIF channels
-
DIF Pattern Generator Sample Application — output arbitrary bit patterns from RAM on DIF channels
Prerequisites:
-
NAI board with a supported DIF module installed (D8, DF1, DF2, DF3, or CMH)
-
SSK 1.x built and ready to run
-
A digital signal source connected to the channel you want to measure (function generator, another DIF channel in output mode, or any system-level digital signal)
How to run:
Launch the DIF_Measure executable from your build output directory. On the first run the board menu appears so you can configure your connection. Subsequent runs skip the menu if a saved configuration file exists. Once connected, select a card index, module, and channel. The application then presents a measurement operations menu where you select a FIFO mode, start measurement, read FIFO data, check status, and stop measurement.
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 DIF. For details on board connection configuration, see the First Time Setup Guide. |
When the application starts, it calls naiapp_RunBoardMenu() with the configuration file default_DIF_Measure.txt. This file does not ship with the SSK — it is created when you save your connection settings from the board menu. On the first run the board menu always appears. On subsequent runs, if the saved configuration file exists, the menu is skipped and the saved settings are loaded automatically.
After the board connection is established, you are prompted to select a card index and module number. The application retrieves the module ID and verifies it is a DIF module by calling naibrd_DIF_GetChannelCount(). If the channel count is zero, the module is rejected.
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_DIF_FIFO(cardIndex, module, moduleID);
}
Inside Run_DIF_FIFO(), the channel count check occurs:
MaxChannel = naibrd_DIF_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf(" *** Module selection not recognized as DIF module. ***\n\n");
}
else
{
Cfg_DIF_FIFO_Channel(cardIndex, module, ModuleID, MaxChannel);
}
In your own application, use naibrd_GetModuleID() and naibrd_DIF_GetChannelCount() to confirm that a module slot contains a supported DIF module before attempting any measurement operations.
|
Important
|
Common Connection Errors
|
Program Structure
Entry Point
The application entry point is main() (or DIF_FIFO() on VxWorks). It enters the board selection loop and, once a valid DIF module is selected, calls Run_DIF_FIFO() to validate the module and then Cfg_DIF_FIFO_Channel() to run the interactive measurement menu.
Application Parameters
The application tracks configuration state in a naiapp_AppParameters_t structure:
| Field | Description |
|---|---|
|
Zero-based index of the connected board. |
|
One-based module slot number. |
|
Module ID returned by |
|
One-based channel number for measurement operations. |
Your application will need to track the same values. The menu system is a sample convenience — in your own code, set these fields directly and call the API functions.
Command Menu
After selecting a channel, the application presents the DIF Measurement Operations Menu with the following commands:
| Command | Menu Label | Description |
|---|---|---|
|
Select FIFO Mode |
Choose one of ten measurement modes. |
|
Display FIFO Data |
Read and display raw FIFO entries. |
|
Set Counter Interval |
Set the gating interval for frequency/interval counting mode. |
|
Display FIFO Status |
Show FIFO status (empty, full, etc.) and element count. |
|
Start FIFO |
Enable the enhanced trigger to begin capturing measurements. |
|
Stop Measurement |
Disable the enhanced trigger to halt measurement. |
|
Display FIFO Count |
Read the edge count register (counting modes only). |
|
Clear FIFO |
Flush all data from the FIFO buffer. |
The menu system is a sample convenience. In your own code, call the same naibrd_DIF_* API functions directly in whatever sequence your application requires.
Channel Configuration Display
Each time the menu appears, the application reads and displays the current measurement configuration for the selected channel. This gives you immediate feedback on the channel’s state before issuing commands.
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
check_status(naibrd_DIF_GetFIFOStatus(cardIndex, module, chan, &numberOfElements, &fifoStatus));
check_status(naibrd_DIF_GetOpMode(cardIndex, module, chan, &opmode));
check_status(naibrd_DIF_GetTimebaseInterval(cardIndex, module, chan, &interval));
The display shows five values at a glance:
-
Status — the FIFO state: Empty, Almost Empty, Between Empty and Full, Almost Full, or Full
-
Count — the number of elements currently in the FIFO
-
Interval — the timebase interval in milliseconds (displayed only when in interval counting mode, mode 10)
-
Value — the edge count register value (displayed only when in counting modes 6-8)
-
Enhanced Mode Selection — the currently active measurement mode
To read these values in your own application, call naibrd_DIF_GetFIFOStatus() for the FIFO state and element count, naibrd_DIF_GetOpMode() for the current mode, naibrd_DIF_GetTimebaseInterval() for the interval, and naibrd_DIF_GetCountData() for the edge count in counting modes.
|
Important
|
Common Errors
|
Selecting a Measurement Mode
The core of this application is selecting which type of measurement the hardware performs. To configure a measurement mode on a DIF channel, call naibrd_DIF_SetOpMode() with one of the nai_dif_enhanced_mode_t constants, then clear stale data, and enable the enhanced trigger to start capturing.
The ten modes and what they capture at the hardware level:
| Mode | Constant | What the Hardware Captures |
|---|---|---|
1 |
|
Duration the signal is high. The FPGA starts a timer on each rising edge and stops on the falling edge. Each FIFO entry represents one high-pulse width. |
2 |
|
Duration the signal is low. Timer starts on falling edge, stops on rising edge. Each FIFO entry is one low-pulse width. |
3 |
|
Absolute timestamp of each rising edge. The FPGA maintains a free-running counter; each rising edge latches the counter value into the FIFO. |
4 |
|
Absolute timestamp of each falling edge, same mechanism as mode 3 but triggered on falling edges. |
5 |
|
Absolute timestamp of every edge (rising and falling). Fills the FIFO twice as fast as modes 3 or 4. |
6 |
|
Running count of rising edges. Stored in the count register, not the FIFO. |
7 |
|
Running count of falling edges. Count register, not FIFO. |
8 |
|
Running count of all edges. Count register, not FIFO. |
9 |
|
Full period: time from one rising edge to the next. Each FIFO entry is one complete cycle period. |
10 |
|
Edge count over a gated interval. The hardware counts edges during a user-defined time window. The result, combined with the interval, yields frequency. |
The setup sequence for any mode follows the same three-step pattern:
-
Set the mode — call
naibrd_DIF_SetOpMode(). -
Clear stale data — call
naibrd_DIF_ClearFIFO()(timing/timestamp/period modes) ornaibrd_DIF_ClearCountData()(counting modes). This is critical: leftover data from a previous mode will produce meaningless results. -
Enable measurement — call
naibrd_DIF_SetEnhanceTriggerEnable()withNAI_DIF_ENHANCE_OP_ENABLE.
Here is the pattern for a timing mode (mode 1, Measure High Time):
check_status(naibrd_DIF_SetOpMode(cardIndex, module, chan, NAI_DIF_MODE_MEASURE_HIGH_TIME));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
And for a counting mode (mode 6, Count Rising Edges):
check_status(naibrd_DIF_SetOpMode(cardIndex, module, chan, NAI_DIF_MODE_COUNT_RISING_EDGES));
/* clear old count value since we are changing modes */
check_status(naibrd_DIF_ClearCountData(cardIndex, module, chan));
/* now start the counter in the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
Note the difference: timing and timestamp modes call naibrd_DIF_ClearFIFO() to flush the FIFO buffer, while counting modes call naibrd_DIF_ClearCountData() to zero the count register. Using the wrong clear function will leave stale data in place.
For mode 10 (interval counting / frequency measurement), there is an additional step — setting the gating interval — which is covered in the next section.
|
Important
|
Common Errors
|
Interval Counting and Frequency Measurement
Mode 10 (NAI_DIF_MODE_MEASURE_FREQUENCY) adds a gating interval to the counting mechanism. Instead of counting edges indefinitely, the hardware counts edges during a fixed time window (the interval), stores the result, resets, and starts counting again. Each FIFO entry represents the number of edges counted during one interval.
This is the hardware mechanism for frequency measurement: if you set the interval to 1000 ms (1 second), each FIFO entry is the number of edges per second — a direct frequency reading in Hz. If you set a shorter interval (e.g., 100 ms), divide the count by the interval in seconds to get frequency.
To configure the interval, call naibrd_DIF_SetTimebaseInterval() with the desired interval in milliseconds:
check_status(naibrd_DIF_SetOpMode(cardIndex, module, chan, NAI_DIF_MODE_MEASURE_FREQUENCY));
/* Set the interval */
check_status(Configure_DIF_Counter_Interval(paramCount, p_params));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
The interval configuration itself queries the module’s timebase LSB (least significant bit) to determine the valid range:
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
interval = atof((const char *)inputBuffer); /*entry in milliseconds*/
lsb = naibrd_DIF_GetTimebaseLSB(ModuleID);
switch (ModuleID)
{
case NAI_MODULE_ID_DF2:
min = (float64_t)(0x2u * lsb);
max = (float64_t)(0xFFFFFFFF * lsb);
default:
break;
}
if (interval > max || interval < min)
printf(" Entry out of range. Range %7.7f to %7.3f ms\n", min, max);
else
{
check_status(naibrd_DIF_SetTimebaseInterval(cardIndex, module, chan, interval));
}
The valid interval range depends on the module’s timebase resolution. Call naibrd_DIF_GetTimebaseLSB() with the module ID to get the LSB value in milliseconds, then compute the minimum (2 x LSB) and maximum (0xFFFFFFFF x LSB) intervals. Consult your module’s manual for the exact timebase resolution of your module type.
In your own application, call naibrd_DIF_SetTimebaseInterval() directly with your desired interval. For a 1000 ms interval that yields direct Hz readings, pass 1000.0.
|
Important
|
Common Errors
|
Starting and Stopping Measurement
Measurement is controlled by the enhanced trigger enable register. To start capturing data, call naibrd_DIF_SetEnhanceTriggerEnable() with NAI_DIF_ENHANCE_OP_ENABLE. To stop, call the same function with NAI_DIF_ENHANCE_OP_DISABLE.
Starting measurement (the Go command):
check_status(naibrd_DIF_SetEnhanceTriggerEnable(p_dif_params->cardIndex,
p_dif_params->module, p_dif_params->channel,
NAI_DIF_ENHANCE_OP_ENABLE));
Stopping measurement (the STOP command):
status = check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan,
NAI_DIF_ENHANCE_OP_DISABLE));
if (status == NAI_SUCCESS)
printf("Measurement stopped, mode reset\n");
In your own application, start and stop measurement as needed. The hardware continues capturing into the FIFO while the trigger is enabled, regardless of whether you are reading the FIFO. If you leave measurement running and do not read the FIFO, it will eventually fill up and stop recording new data. Monitor the FIFO status to avoid data loss.
|
Important
|
Common Errors
|
Reading FIFO Data
To read measurement results from the FIFO, first check how many elements are available, then read them with naibrd_DIF_ReadFIFORawEx().
/* First check how many elements are on the FIFO */
check_status(naibrd_DIF_GetFIFOStatus(cardIndex, module, chan, &numberOfElements, &outstatus));
Then read the requested number of elements:
check_status(naibrd_DIF_ReadFIFORawEx(cardIndex, module, chan, count, timeout, outdata,
&numberOfElements, &countRemaining));
for (i = 0; i < count; i++)
{
printf("FIFO element %d 0x%x\n", i, outdata[i]);
}
if (count > 0)
printf("\n%d items left in the FIFO\n", countRemaining);
API parameters:
-
cardIndex,module,chan— identify the board, module slot, and channel. -
count— the number of elements to read. Must not exceed the number of available elements. -
timeout— maximum wait time in hardware ticks. The sample uses0xFFFFFFFF(maximum wait). -
outdata— buffer to receive the raw FIFO data. The sample allocates 512 elements. -
numberOfElements— output: the actual number of elements read. -
countRemaining— output: the number of elements still in the FIFO after the read.
The data is returned as raw 32-bit values. The interpretation depends on the active measurement mode:
-
Timing modes (1, 2, 9) — each value represents a time duration in hardware time units (determined by the module’s timebase LSB). Multiply by the LSB to convert to milliseconds.
-
Timestamp modes (3, 4, 5) — each value is an absolute timestamp from the module’s free-running counter. Subtract consecutive timestamps to get the time between edges.
-
Interval counting mode (10) — each value is the number of edges counted during one gating interval.
Counting modes (6, 7, 8) do not use the FIFO. Instead, read the count register with naibrd_DIF_GetCountData():
check_status(naibrd_DIF_GetCountData(p_dif_params->cardIndex, p_dif_params->module,
p_dif_params->channel, &outcount));
printf("Count is %d\n", outcount);
|
Important
|
Common Errors
|
Checking FIFO Status
To check the FIFO state without reading data, call naibrd_DIF_GetFIFOStatus():
check_status(naibrd_DIF_GetFIFOStatus(cardIndex, module, chan, &numberOfElements, &fifoStatus));
The fifoStatus value is one of:
| Status Constant | Meaning |
|---|---|
|
No elements in the FIFO. |
|
A few elements present, below the almost-empty threshold. |
|
Normal operating range — data is present and the buffer is not near capacity. |
|
The FIFO is approaching capacity. Read data soon to avoid overflow. |
|
The FIFO is full. New measurements are being discarded until you read or clear the buffer. |
Use the status in your application to decide when to read. A common pattern is to poll the status and read when the FIFO reaches a certain fill level, or to read periodically and check numberOfElements to ensure you are keeping up with the data rate.
Clearing the FIFO
To flush all data from the FIFO, call naibrd_DIF_ClearFIFO():
check_status(naibrd_DIF_ClearFIFO(p_dif_params->cardIndex, p_dif_params->module,
p_dif_params->channel));
Always clear the FIFO when switching measurement modes. Data from a previous mode is not valid for the new mode and will produce incorrect results if read.
For counting modes, clear the count register instead:
check_status(naibrd_DIF_ClearCountData(cardIndex, module, chan));
Troubleshooting Reference
This section summarizes the errors and symptoms covered in the preceding sections. Consult your module’s manual for hardware-specific diagnostics and FPGA revision requirements.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Physical connection issue; wrong connection type configured |
Verify cabling and board menu connection settings. |
|
Selected module is not a DIF module |
Verify the module slot contains a D8, DF1, DF2, DF3, or CMH module. |
|
Module or firmware does not support the requested enhanced mode |
Check your module’s manual for supported modes and required FPGA revision. |
FIFO empty when data is expected |
Trigger not enabled; no signal transitions; mode not set |
Verify |
Stale or garbage data after mode change |
FIFO or count register not cleared before starting new mode |
Always call |
FIFO Full — data loss |
Data accumulating faster than it is being read |
Read the FIFO more frequently, or stop measurement before the buffer fills. |
Interval out of range |
Value below minimum (2 x LSB) or above maximum (0xFFFFFFFF x LSB) |
Call |
Frequency reading incorrect |
Interval not set to 1000 ms; forgot to divide count by interval |
For direct Hz readings, use a 1000 ms interval. Otherwise, divide the count by the interval in seconds. |
Count register reads 0 in counting mode |
Count was cleared but trigger was not enabled; or no edges have occurred |
Verify the trigger is enabled and the input signal has the expected edge transitions. |
FIFO status shows "Unknown" |
Unexpected status register value; possible firmware incompatibility |
Verify module firmware version. Consult your module’s manual for FPGA revision requirements. |
Full Source
Full Source — DIF_Measure.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_dif.h"
#include "advanced/nai_ether_adv.h"
static const int8_t *CONFIG_FILE = (int8_t *)"default_DIF_Measure.txt";
/* Function prototypes */
void Run_DIF_FIFO(int32_t cardIndex, int32_t module, int32_t ModuleID);
void Cfg_DIF_FIFO_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
static void Display_DIF_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
nai_status_t Configure_DIF_FIFO_Mode(int32_t paramCount, int32_t* p_params);
nai_status_t Start_DIF_FIFO(int32_t paramCount, int32_t* p_params);
nai_status_t Clear_DIF_FIFO(int32_t paramCount, int32_t* p_params);
nai_status_t Get_DIF_FIFO_Data(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DIF_Counter_Interval(int32_t paramCount, int32_t* p_params);
nai_status_t Get_DIF_FIFO_Status(int32_t paramCount, int32_t* p_params);
nai_status_t Get_DIF_FIFO_Count(int32_t paramCount, int32_t* p_params);
static const int32_t DEF_DIF_CHANNEL = 2;
/****** Command Table *******/
enum dif_fifo_commands
{
DIF_FIFO_CMD_MODE,
DIF_FIFO_CMD_GET_DATA,
DIF_FIFO_CMD_FIFO_FREQ,
DIF_FIFO_CMD_STATUS,
DIF_FIFO_CMD_FIFO_START,
DIF_FIFO_CMD_FIFO_STOP,
DIF_FIFO_CMD_COUNT,
DIF_FIFO_CMD_FIFO_CLEAR,
DIF_FIFO_CMD_LAST
};
/****** Command Tables *******/
naiapp_cmdtbl_params_t DIF_FIFO_MenuCmds[] = {
{"Mode", "DIF Select FIFO Mode", DIF_FIFO_CMD_MODE, Configure_DIF_FIFO_Mode},
{"Disp", "DIF Display FIFO Data", DIF_FIFO_CMD_GET_DATA, Get_DIF_FIFO_Data},
{"Intv", "DIF Set Counter Interval", DIF_FIFO_CMD_FIFO_FREQ, Configure_DIF_Counter_Interval},
{"Stat", "DIF Display FIFO Status", DIF_FIFO_CMD_STATUS, Get_DIF_FIFO_Status},
{"Go", "DIF Start FIFO/Clear count", DIF_FIFO_CMD_FIFO_START, Start_DIF_FIFO},
{"STOP", "DIF Stop Measurement", DIF_FIFO_CMD_FIFO_STOP, NULL},
{"Count", "DIF Display FIFO Count", DIF_FIFO_CMD_COUNT, Get_DIF_FIFO_Count},
{"R", "DIF Clear FIFO", DIF_FIFO_CMD_FIFO_CLEAR, Clear_DIF_FIFO}
};
/**************************************************************************************************************/
/**
<summary>
The purpose of the DIF_FIFO is to illustrate the methods to call in the naibrd library to perform DIF enhanced
FIFO mode. This example code will configure DIF FIFO to desired mode, start, stop and display the DIF FIFO
The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd DIF routines.
- ClearDeviceCfg
- QuerySystemCfg
- DisplayDeviceCfg
- GetBoardSNModCfg
- SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DIF_FIFO(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_DIF_FIFO(cardIndex, module, moduleID);
}
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
Run_DIF_FIFO prompts the user for the card, module and channel to use for the application and calls
Cfg_DIF_Channel if the card, module, channel is valid for as a discrete module.
</summary>
*/
/**************************************************************************************************************/
void Run_DIF_FIFO(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
int32_t MaxChannel;
MaxChannel = naibrd_DIF_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf(" *** Module selection not recognized as DIF module. ***\n\n");
}
else
{
Cfg_DIF_FIFO_Channel(cardIndex, module, ModuleID, MaxChannel);
}
}
/**************************************************************************************************************/
/**
<summary>
Cfg_DIF_FIFO_Channel handles calling the Display_DIF_ChannelCfg routine to display the discrete channel configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
void Cfg_DIF_FIFO_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
bool_t bCmdFound = FALSE;
int32_t chan, defaultchan = 1;
int32_t cmd;
int32_t status;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiapp_AppParameters_t dif_params;
p_naiapp_AppParameters_t dif_measure_params = &dif_params;
dif_measure_params->cardIndex = cardIndex;
dif_measure_params->module = module;
dif_measure_params->modId = ModuleID;
while (bContinue)
{
printf(" \r\n\r\n");
printf("Channel selection \r\n");
printf("================= \r\n");
defaultchan = DEF_DIF_CHANNEL;
bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);
dif_measure_params->channel = chan;
naiapp_utils_LoadParamMenuCommands(DIF_FIFO_CMD_LAST, DIF_FIFO_MenuCmds);
while (bContinue)
{
Display_DIF_ChannelCfg(cardIndex, module, chan, ModuleID);
naiapp_display_ParamMenuCommands((int8_t *)"DIF Measurement Operations Menu");
printf("\nType DIF command or %c to quit :\n > ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case DIF_FIFO_CMD_MODE:
case DIF_FIFO_CMD_FIFO_START:
case DIF_FIFO_CMD_FIFO_CLEAR:
case DIF_FIFO_CMD_GET_DATA:
case DIF_FIFO_CMD_FIFO_FREQ:
case DIF_FIFO_CMD_STATUS:
case DIF_FIFO_CMD_COUNT:
DIF_FIFO_MenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)dif_measure_params);
break;
case DIF_FIFO_CMD_FIFO_STOP:
{
status = check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_DISABLE));
if (status == NAI_SUCCESS)
printf("Measurement stopped, mode reset\n");
}
break;
default:
printf("Invalid command entered\n");
break;
}
}
else
printf("Invalid command entered\n");
}
}
else
bContinue = FALSE;
}
}
}
/**************************************************************************************************************/
/**
<summary>
Display_DIF_ChannelCfg illustrate the methods to call in the naibrd library to retrieve the configuration states
for measurement operation.
</summary>
*/
/**************************************************************************************************************/
static void Display_DIF_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
float64_t interval= 0.0;
uint32_t numberOfElements = 0;
nai_dif_fifo_status_t fifoStatus = 0;
nai_dif_enhanced_mode_t opmode = 0;
uint32_t outcount = 0;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
check_status(naibrd_DIF_GetFIFOStatus( cardIndex, module, chan, &numberOfElements, &fifoStatus ));
check_status(naibrd_DIF_GetOpMode(cardIndex, module, chan, &opmode));
check_status(naibrd_DIF_GetTimebaseInterval( cardIndex, module, chan, &interval ));
printf("\n === Channel %d ===\n\n", chan);
/*read DIF FIFO configuration values here, Status, number of elements, interval, and mode */
{
printf(" Status Count Interval Value Enhanced Mode Selection\n");
printf("------------- ------- ---- mS ----- ------- ---------------------------\n");
}
/*display configuration settings here- */
switch (fifoStatus)
{
case NAI_DIF_FIFO_STATUS_ALMOST_EMPTY:
printf(" FIFO almost Empty ");
break;
case NAI_DIF_FIFO_STATUS_EMPTY:
printf(" FIFO Empty ");
break;
case NAI_DIF_FIFO_STATUS_FULL:
printf(" FIFO Full ");
break;
case NAI_DIF_FIFO_STATUS_ALMOST_FULL:
printf(" FIFO Almost Full ");
break;
case NAI_DIF_FIFO_STATUS_BTWN_ALMOST_EMPTY_FULL:
printf(" FIFO Btwn Empty and Full ");
break;
default:
printf(" Unknown ");
break;
}
/* display number of elements on FIFO */
printf(" %3d ", numberOfElements);
/* if opcode is 10 display the interval */
if( opmode == 10 )
printf("%12.3f ", interval);
else
printf("%12.3f NA", interval);
/* if opcode is 6,7,or 8 display the counter value */
if( (opmode > 5) && (opmode < 9) )
{
check_status(naibrd_DIF_GetCountData( cardIndex, module, chan, &outcount ));
printf("%7d ", outcount);
}
else
printf("%7d NA ", outcount);
switch (opmode)
{
case NAI_DIF_MODE_STD_INPUT_OUTPUT:
printf("STD_INPUT_OUTPUT ");
break;
case NAI_DIF_MODE_MEASURE_HIGH_TIME:
printf("MEASURE_HIGH_TIME ");
break;
case NAI_DIF_MODE_MEASURE_LOW_TIME:
printf("MEASURE_LOW_TIME ");
break;
case NAI_DIF_MODE_TIMESTAMP_RISING_EDGES:
printf("TIMESTAMP_RISING_EDGES ");
break;
case NAI_DIF_MODE_TIMESTAMP_FALLING_EDGES:
printf("Record TIMESTAMP_FALLING_EDGES ");
break;
case NAI_DIF_MODE_TIMESTAMP_ALL_EDGES:
printf("Record TIMESTAMP_ALL_EDGES ");
break;
case NAI_DIF_MODE_COUNT_RISING_EDGES:
printf("MODE_COUNT_RISING_EDGES ");
break;
case NAI_DIF_MODE_COUNT_FALLING_EDGES:
printf("MODE_COUNT_FALLING_EDGES ");
break;
case NAI_DIF_MODE_COUNT_ALL_EDGES:
printf("MODE_COUNT_ALL_EDGES ");
break;
case NAI_DIF_MODE_MEASURE_PERIOD_FROM_RISING_EDGE:
printf("MEASURE_PERIOD_FROM_RISING_EDGE ");
break;
case NAI_DIF_MODE_MEASURE_FREQUENCY:
printf("Measure Interval Count ");
break;
case NAI_DIF_MODE_OUTPUT_PWM_FOREVER:
printf("Continuous PWM Output");
break;
case NAI_DIF_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES:
printf("Burst PWM Output");
break;
case NAI_DIF_MODE_OUTPUT_PATTERN_RAM:
printf("NAI_DIF_MODE_OUTPUT_PATTERN_RAM ");
break;
default:
printf("Unknown ");
break;
}
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_FIFO_Mode handles the user request to select the FIFO mode for the selected channel
and calls the method in the naibrd library to set the mode.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DIF_FIFO_Mode(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t selection = 0;
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_dif_params->cardIndex;
int32_t module = p_dif_params->module;
int32_t chan = p_dif_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\n == FIFO Mode Selection == \n");
printf(" 1 Measure high time\n");
printf(" 2 Measure low time\n");
printf(" 3 Timestamp of all rising edges\n");
printf(" 4 Timestamp of all falling edges\n");
printf(" 5 Timestamp of all edges\n");
printf(" 6 Count total number of rising edges\n");
printf(" 7 Count total number of falling edges\n");
printf(" 8 Count total number of all edges\n");
printf(" 9 Measure period from rising edge\n");
printf("10 Measure Interval count / frequency\n");
printf(" > ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
selection = atoi((const char *)inputBuffer);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
/* Must be in enhanced mode to use DIF FIFO */
if (selection == 1)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_MEASURE_HIGH_TIME));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 2)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_MEASURE_LOW_TIME));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 3)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_TIMESTAMP_RISING_EDGES));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 4)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_TIMESTAMP_FALLING_EDGES));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 5)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_TIMESTAMP_ALL_EDGES));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 6)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_COUNT_RISING_EDGES));
/* clear old count value since we are changing modes */
check_status(naibrd_DIF_ClearCountData(cardIndex, module, chan));
/* now start the counter in the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 7)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_COUNT_FALLING_EDGES));
/* clear old count value since we are changing modes */
check_status(naibrd_DIF_ClearCountData(cardIndex, module, chan));
/* now start the counter in the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 8)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_COUNT_ALL_EDGES));
/* clear old count value since we are changing modes */
check_status(naibrd_DIF_ClearCountData(cardIndex, module, chan));
/* now start the counter in the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 9)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_MEASURE_PERIOD_FROM_RISING_EDGE));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else if (selection == 10)
{
check_status(naibrd_DIF_SetOpMode( cardIndex, module, chan, NAI_DIF_MODE_MEASURE_FREQUENCY));
/* Set the interval */
check_status(Configure_DIF_Counter_Interval(paramCount, p_params));
/* clear old data from FIFO since we are changing modes */
check_status(naibrd_DIF_ClearFIFO(cardIndex, module, chan));
/* now start the FIFO */
check_status(naibrd_DIF_SetEnhanceTriggerEnable(cardIndex, module, chan, NAI_DIF_ENHANCE_OP_ENABLE));
}
else
{
printf("Invalid mode %d\n", selection);
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Start_DIF_FIFO must be called in order to start the FIFO in a particular mode.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Start_DIF_FIFO(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_DIF_SetEnhanceTriggerEnable(p_dif_params->cardIndex, p_dif_params->module, p_dif_params->channel, NAI_DIF_ENHANCE_OP_ENABLE));
return NAI_ERROR_UNKNOWN;
}
/**************************************************************************************************************/
/**
<summary>
Clear_DIF_FIFO should be called before naibrd_DIF_StartMeasurement to clear out old data.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Clear_DIF_FIFO(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_DIF_ClearFIFO( p_dif_params->cardIndex, p_dif_params->module, p_dif_params->channel ));
return NAI_ERROR_UNKNOWN;
}
/**************************************************************************************************************/
/**
<summary>
Get_DIF_FIFO_Data reads back the data on the FIFO.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Get_DIF_FIFO_Data(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_dif_params->cardIndex;
int32_t module = p_dif_params->module;
int32_t chan = p_dif_params->channel;
uint32_t count, numberOfElements, i, countRemaining, timeout;
uint32_t outdata[512];
bool_t bQuit = FALSE;
nai_dif_fifo_status_t outstatus;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
timeout = (0xFFFFFFFFu);
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
/* First check how many elements are on the FIFO */
check_status(naibrd_DIF_GetFIFOStatus( cardIndex, module, chan, &numberOfElements, &outstatus ));
printf("\nThere is %d elements on FIFO, please enter number to display (Hit Enter for all):\n > ", numberOfElements);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
count = atoi((const char *)inputBuffer);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
count = atoi((const char *)inputBuffer);
if( count > numberOfElements )
count = numberOfElements;
if( count < 0 )
count = 0;
}
else
count = numberOfElements;
check_status(naibrd_DIF_ReadFIFORawEx(cardIndex, module, chan, count, timeout, outdata, &numberOfElements, &countRemaining));
for (i = 0;i < count;i++)
{
printf("FIFO element %d 0x%x\n", i, outdata[i]);
}
if (count>0)
printf("\n%d items left in the FIFO\n", countRemaining);
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_Counter_Interval will configure DIF module gating interval for measurement of counts within the user defined interval.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DIF_Counter_Interval(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
float64_t interval = 0.0;
float64_t lsb = 0;
float64_t min = 1;
float64_t max = -1;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_dif_params->cardIndex;
int32_t module = p_dif_params->module;
int32_t chan = p_dif_params->channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\nEnter the desired interval in ms \n(Enter 1000 for direct frequency reading):\n > ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
interval = atof((const char *)inputBuffer); /*entry in milliseconds*/
lsb = naibrd_DIF_GetTimebaseLSB(ModuleID);
switch (ModuleID)
{
case NAI_MODULE_ID_DF2:
min =(float64_t)(0x2u * lsb);
max =(float64_t)(0xFFFFFFFF * lsb);
default:
break;
}
if (interval > max || interval < min)
printf(" Entry out of range. Range %7.7f to %7.3f ms\n", min, max);
else
{
check_status(naibrd_DIF_SetTimebaseInterval(cardIndex, module, chan, interval ));
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Get_DIF_FIFO_Count will read back the value of the counter if the FIFO is configured for
* opmode 6,7, or 8.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Get_DIF_FIFO_Count(int32_t paramCount, int32_t* p_params)
{
uint32_t outcount;
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_DIF_GetCountData(p_dif_params->cardIndex, p_dif_params->module, p_dif_params->channel, &outcount ));
printf("Count is %d\n",outcount);
return NAI_ERROR_UNKNOWN;
}
/**************************************************************************************************************/
/**
<summary>
Get_DIF_FIFO_Status will read back the value of the counter if the FIFO is configured for
* opmode 6,7, or 8.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Get_DIF_FIFO_Status(int32_t paramCount, int32_t* p_params)
{
uint32_t numberOfElements;
nai_dif_fifo_status_t fifoStatus;
p_naiapp_AppParameters_t p_dif_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_dif_params->cardIndex;
int32_t module = p_dif_params->module;
int32_t chan = p_dif_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_DIF_GetFIFOStatus( cardIndex, module, chan, &numberOfElements, &fifoStatus ));
switch (fifoStatus)
{
case NAI_DIF_FIFO_STATUS_ALMOST_EMPTY:
printf(" FIFO almost Empty ");
break;
case NAI_DIF_FIFO_STATUS_EMPTY:
printf(" FIFO Empty ");
break;
case NAI_DIF_FIFO_STATUS_FULL:
printf(" FIFO Full ");
break;
case NAI_DIF_FIFO_STATUS_ALMOST_FULL:
printf(" FIFO Almost Full ");
break;
case NAI_DIF_FIFO_STATUS_BTWN_ALMOST_EMPTY_FULL:
printf(" FIFO Btwn Empty and Full ");
break;
default:
printf(" Unknown ");
break;
}
return NAI_ERROR_UNKNOWN;
}