AD FIFO
Edit this on GitLab
AD FIFO Sample Application (SSK 2.x)
Overview
The AD FIFO sample application demonstrates how to use the FIFO buffering capability of analog-to-digital modules with the NAI Software Support Kit (SSK 2.x). Unlike the AD BasicOps sample which reads individual channel values, this sample focuses on configuring the FIFO to collect data at a programmable sample rate and then extracting the buffered data for processing. It covers FIFO configuration (thresholds, sample rate, delay, trigger control, buffer control), software triggering, reading FIFO data in both large-quantity and 256-element batches, and monitoring FIFO status.
This sample supports the following AD module types: AD1 through AD6, ADE through ADG. For AD4, AD5, and AD6 modules, the sample also demonstrates channel activation — these modules require channels to be explicitly activated before FIFO data collection begins. For detailed module specifications, refer to the AD1-AD3 Manual and AD4-AD6 Manual.
For the SSK 1.x version, see AD FifoMenu (SSK 1.x).
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an AD module installed (AD1-AD6, ADE-ADG).
-
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 ad_fifo executable from your build output directory. On startup the application looks for a configuration file (default_AD_fifo.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection. Once connected, the application displays current FIFO configuration for all channels and presents a command menu for configuring and operating the FIFO.
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 AD FIFO. |
The main() function follows a standard SSK 2.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_AD_fifo.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_GetModuleName()so downstream code can adapt to the specific AD variant installed.
#if defined (__VXWORKS__)
int32_t AD_FifoMenu(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex = 0;
int32_t moduleCnt = 0;
int32_t module = 0;
uint32_t moduleID = 0u;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0;
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)
{
naibrd_GetModuleName(cardIndex, module, &moduleID);
if ((moduleID != 0))
{
ADFIFO_RunMenu(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:
-
The VxWorks preprocessor guard uses
__VXWORKS__in this particular sample (most SSK 2.x samples useNAIBSP_CONFIG_SOFTWARE_OS_VXWORKS). -
The module identifier is retrieved with
naibrd_GetModuleName()(SSK 1.x usesnaibrd_GetModuleID()). -
Boolean constants are
NAI_TRUE/NAI_FALSE(SSK 1.x usesTRUE/FALSE). -
Console output uses
naiif_printf()from the platform abstraction layer (SSK 1.x usesprintf()directly).
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms (Petalinux, Windows) the entry point is main(). On VxWorks the entry point is AD_FifoMenu():
#if defined (__VXWORKS__)
int32_t AD_FifoMenu(void)
#else
int32_t main(void)
#endif
Command Loop
After connecting to the board and selecting a module, the application calls ADFIFO_RunMenu(). For AD4/AD5/AD6 modules, it first deactivates all channels by writing zero to the active channels register. The menu loop displays the current FIFO configuration for all channels, then presents the command menu and dispatches user selections.
The command table defines the following operations:
| Command | Description |
|---|---|
|
Configure FIFO parameters for a channel (range, thresholds, sample rate, delay, skip count, FIFO size, buffer control, trigger control). |
|
Issue a software trigger to start FIFO data collection. |
|
Issue a software trigger and measure the elapsed time until the FIFO sample-done flag is set. |
|
Read data from the FIFO in large quantities (uses raw 32-bit reads with manual conversion). |
|
Read data from the FIFO in 256-element batches (uses the convenience |
|
Display FIFO status registers for all channels. |
|
Clear the FIFO for a selected channel. |
Configuring the FIFO
The ADFIFO_ConfigChannel() function walks the user through a series of prompts to configure all FIFO parameters for a selected channel:
static nai_status_t ADFIFO_ConfigChannel(int32_t paramCount, int32_t* p_params)
{
/* Prompt for: range/polarity, low threshold, high threshold,
almost-empty threshold, almost-full threshold, sample rate,
delay, skip count, FIFO size, buffer control, trigger control */
check_status(naibrd_AD_SetRangePolarity(cardIndex, module, channel, polarity, range));
check_status(naibrd_AD_SetFIFOLoThreshold(cardIndex, module, channel, loThreshold));
check_status(naibrd_AD_SetFIFOHiThreshold(cardIndex, module, channel, hiThreshold));
check_status(naibrd_AD_SetFIFODelay(cardIndex, module, channel, sampleDelay));
check_status(naibrd_AD_SetFIFOSize(cardIndex, module, channel, samplesPerTrigger));
check_status(naibrd_AD_SetSampleRate(cardIndex, module, sampleRate));
check_status(naibrd_AD_SetFIFOCtrl(cardIndex, module, channel, bufferControl));
check_status(naibrd_AD_SetFIFOTrigCtrl(cardIndex, module, channel, g_triggerControl));
check_status(naibrd_AD_SetFIFOAlmostEmpty(cardIndex, module, channel, almostEmpty));
check_status(naibrd_AD_SetFIFOAlmostFull(cardIndex, module, channel, almostFull));
check_status(naibrd_AD_SetFIFOSkip(cardIndex, module, channel, skipCount));
}
Key configuration parameters:
-
Low/High Threshold — FIFO fill-level thresholds that generate status flags when crossed.
-
Almost Empty/Full — Additional threshold levels for monitoring FIFO fill state.
-
Sample Rate — The rate at which A/D samples are collected (max 250,000 samples/second).
-
Delay — Number of samples to delay before collection begins after a trigger.
-
Skip Count — Number of samples to skip between collected samples.
-
FIFO Size — Number of samples to collect per trigger event.
-
Buffer Control — Bit-mapped register controlling filter mode (bit 2) and timestamp interleaving (bit 4).
-
Trigger Control — Bit-mapped register controlling trigger type (continuous vs single-sample), trigger edge, and trigger enable.
|
Note
|
For AD4, AD5, and AD6 modules, a channel must be set to ACTIVE before it can collect FIFO data. The application prompts the user and calls naibrd_AD_SetActiveChannel() during configuration.
|
Software Trigger and Timing
The ADFIFO_SwTrigger() function issues a software trigger to begin data collection:
check_status(naibrd_AD_SoftwareTrigger(p_ad_params->cardIndex, p_ad_params->module));
The ADFIFO_SwTriggerMeasTime() function provides a timed trigger that measures how long it takes for the FIFO to complete sampling. It clears the FIFO, enables the trigger, issues a software trigger, then polls the FIFO status register for the done flag with a 5-second timeout.
Reading FIFO Data
The application provides two methods for reading FIFO data:
Large Quantity Read (R command)
The ADFIFO_PrintSamplesInFifo() function reads raw 32-bit FIFO data and converts it to voltages:
status = naibrd_AD_ReadFIFORaw32(cardIndex, module, channel,
samplesToRead >= NAIAPP_FIFO_BUFFER_SIZE ? NAIAPP_FIFO_BUFFER_SIZE : samplesToRead,
g_dataRaw, &samplesRead);
/* Convert raw data to voltages */
check_status(naibrd_AD_ConvertToData(modid, NAIBRD_AD_MODE_VOLTAGE, rangeRaw,
samplesRead, g_dataRaw, &p_data));
This method reads in chunks of up to 1000 elements, handles timestamp-interleaved data, and displays both raw hex and converted voltage values.
256-Element Read (R256 command)
The ADFIFO_PrintSamplesInFifo256() function uses the convenience API that handles conversion internally:
status = naibrd_AD_ReadFIFO(cardIndex, module, channel, samplesToRead, g_data, &read);
This API is limited to 256 elements per call because it allocates a temporary buffer on the stack.
Displaying FIFO Status
The ADFIFO_DisplayFifoStatus() function reads and decodes the FIFO status register for all channels:
check_status(naibrd_AD_GetEventMappedStatusRaw(cardIndex, module, channel,
NAI_STATUS_REALTIME, NAIBRD_AD_FIFO_STATUS, (uint32_t*)&fifoStatus));
The status register bits indicate: Sample Done, FIFO Full, High Limit, Low Limit, Empty, Almost Empty, and Almost Full.
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
FIFO buffer is empty after trigger |
Channel not activated (AD4/AD5/AD6), trigger control not enabled, or FIFO size set to zero. |
Ensure the channel is active, trigger control has the enable bit set (0x1XX), and FIFO size is non-zero. |
Sample Done timeout |
Sample rate too low relative to FIFO size, or trigger not reaching the module. |
Increase sample rate or decrease FIFO size. Verify the trigger control register is configured correctly. |
No board found |
Board not powered, cable disconnected, or wrong interface selected. |
Verify power, cables, and that the correct interface type is chosen in the board menu. |
Connection timeout |
Incorrect IP address, firewall blocking communication, or network misconfiguration. |
Confirm the board IP address. Disable or configure firewall rules. |
Invalid card or module index |
Indices are zero-based for cards and one-based for modules. |
Ensure the values you enter match your hardware setup. |
NAI_ERROR_MORE_DATA returned |
More data exists in the FIFO than was requested. This is informational, not a fatal error. |
The application suppresses this status. You can loop to read remaining data or ignore it. |
Timestamp data appears garbled |
Buffer control register does not have the timestamp bit set, but data is being read as timestamped. |
Ensure the buffer control register bit 4 matches your expectation. When timestamps are enabled, FIFO count includes both data and timestamp entries. |
Data values appear incorrect |
Range/polarity mismatch between configuration and conversion. |
Ensure the range and polarity set during configuration match the values used for |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — ad_fifo.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_ad.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"
/* AD Sample App include files */
#include "nai_sample_apps/naiapp_src/board_modules/ad/ad_common_utils/ad_common_utils.h"
static const int8_t *SAMPLE_PGM_NAME = (const int8_t *)"AD Module FIFO Operation Program";
static const int8_t *CONFIG_FILE = (const int8_t *)"default_AD_fifo.txt";
/* Function prototypes */
static bool_t ADFIFO_RunMenu(int32_t cardIndex, int32_t module, uint32_t modid);
static void ADFIFO_displayChannelCfg(int32_t cardIndex, int32_t module, int32_t MAX_CHANNELS);
/* AD FIFO Command Functions */
static nai_status_t ADFIFO_SwTrigger(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_SwTriggerMeasTime(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_PrintSamplesInFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_PrintSamplesInFifo256(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_DisplayFifoStatus(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_ClearFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t ADFIFO_ConfigChannel(int32_t paramCount, int32_t* p_params);
/* Additional Helper Functions */
static void ADFIFO_printBufferRequest();
static void ADFIFO_printTriggerCtrlRequest();
static bool_t TimestampEnabled(int32_t cardIndex, int32_t module, int32_t channel);
static void ADFIFO_GetFifoReadInfo(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_inout_samplesToRead, bool_t* p_outbufferControls);
static uint32_t g_triggerControl = 304;
#define NAIAPP_FIFO_BUFFER_SIZE 1000
static uint32_t g_dataRaw[NAIAPP_FIFO_BUFFER_SIZE];
static float64_t g_data[NAIAPP_FIFO_BUFFER_SIZE];
/****** Command Table *******/
/*** Invariant: enumeration of cmd table starts from 0 and increments by 1 ***/
enum ad_fifo_commands
{
AD_FIFO_CMD_CONFIG,
AD_FIFO_CMD_SW_TRIGGER,
AD_FIFO_CMD_SW_TRIGGER_MEAS_TIME,
AD_FIFO_CMD_READ_FIFO,
AD_FIFO_CMD_READ_FIFO_256,
AD_FIFO_CMD_DISPLAY_FIFO_STATUS,
AD_FIFO_CMD_CLEAR_FIFO,
AD_FIFO_CMD_COUNT
};
naiapp_cmdtbl_params_t AD_FifoMenuCmds[] = {
{"CFG", "Configure FIFO", AD_FIFO_CMD_CONFIG, ADFIFO_ConfigChannel},
{"T", "Software Trigger", AD_FIFO_CMD_SW_TRIGGER, ADFIFO_SwTrigger},
{"TM", "Software Trigger & Measure Elapse Time", AD_FIFO_CMD_SW_TRIGGER_MEAS_TIME, ADFIFO_SwTriggerMeasTime},
{"R", "Read data from FIFO, large quantity", AD_FIFO_CMD_READ_FIFO, ADFIFO_PrintSamplesInFifo},
{"R256", "Read data from FIFO, 256 at once", AD_FIFO_CMD_READ_FIFO_256, ADFIFO_PrintSamplesInFifo256},
{"STAT", "Display FIFO Status", AD_FIFO_CMD_DISPLAY_FIFO_STATUS, ADFIFO_DisplayFifoStatus},
{"CL", "Clear FIFO", AD_FIFO_CMD_CLEAR_FIFO, ADFIFO_ClearFifo},
};
#if defined (__VXWORKS__)
int32_t AD_FifoMenu(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex = 0;
int32_t moduleCnt = 0;
int32_t module = 0;
uint32_t moduleID = 0u;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0;
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)
{
naibrd_GetModuleName(cardIndex, module, &moduleID);
if ((moduleID != 0))
{
ADFIFO_RunMenu(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 bool_t ADFIFO_RunMenu(int32_t cardIndex, int32_t module, uint32_t modid)
{
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0;
bool_t bCmdFound = NAI_FALSE;
naiapp_AppParameters_t ad_fifoOps_params;
int32_t cmd = 0;
ad_fifoOps_params.cardIndex = cardIndex;
ad_fifoOps_params.module = module;
ad_fifoOps_params.channel = 1;
ad_fifoOps_params.modId = modid;
ad_fifoOps_params.maxChannels = naibrd_AD_GetChannelCount(modid);
if ((modid == NAIBRD_MODULE_ID_AD4) || (modid == NAIBRD_MODULE_ID_AD5) || (modid == NAIBRD_MODULE_ID_AD6))
{
check_status(naibrd_AD_SetRaw(cardIndex, module, NAIBRD_AD_RAW_ACTIVE_CHANNELS, 0x0)); // Deactivate all channels
}
naiapp_utils_LoadParamMenuCommands(AD_FIFO_CMD_COUNT, AD_FifoMenuCmds);
do
{
ADFIFO_displayChannelCfg(cardIndex, module, ad_fifoOps_params.maxChannels);
naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_PGM_NAME);
naiif_printf("\r\n\r\nPlease enter a command or 'q' to quit:");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
AD_FifoMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)&ad_fifoOps_params);
}
else
{
naiif_printf("Invalid command entered\r\n");
}
}
} while (!bQuit);
return bQuit;
}
static void ADFIFO_displayChannelCfg(int32_t cardIndex, int32_t module, int32_t MAX_CHANNELS)
{
uint32_t loThreshold = 0u, hiThreshold = 0u, wordsInFifo = 0u, sampleDelay = 0u, almostEmpty = 0u, almostFull = 0u;
uint32_t fifoSize = 0u, sampleRate = 0u, bufferControl = 0u, triggerControl = 0u, skipCount = 0u;
uint32_t fifoStatus = 0u;
int32_t channel = 0;
uint32_t modid = 0u;
naibrd_GetModuleName(cardIndex, module, &modid);
naiif_printf( "\r\n Words High Low Almost Almost Size");
naiif_printf( "\r\n in Thres- Thres- Empty Full Sample Skip of Sample Buffer Trig Status");
naiif_printf( "\r\nChan Fifo hold hold Delay Count FIFO Rate Ctrl Ctrl Register");
naiif_printf( "\r\n--------------------------------------------------------------------------------------------------------------------------");
naibrd_AD_GetSampleRate(cardIndex, module, &sampleRate);
for ( channel = 1; channel <= MAX_CHANNELS; channel++ )
{
naibrd_AD_GetFIFOCount(cardIndex, module, channel, &wordsInFifo);
naibrd_AD_GetFIFOLoThreshold(cardIndex, module, channel, &loThreshold);
naibrd_AD_GetFIFOHiThreshold(cardIndex, module, channel, &hiThreshold);
naibrd_AD_GetFIFOAlmostEmpty(cardIndex, module, channel, &almostEmpty);
naibrd_AD_GetFIFOAlmostFull(cardIndex, module, channel, &almostFull);
naibrd_AD_GetFIFODelay(cardIndex, module, channel, &sampleDelay);
naibrd_AD_GetFIFOSkip(cardIndex, module, channel, &skipCount);
naibrd_AD_GetFIFOSize(cardIndex, module, channel, &fifoSize);
naibrd_AD_GetFIFOCtrl(cardIndex, module, channel, &bufferControl);
naibrd_AD_GetFIFOTrigCtrl(cardIndex, module, channel, &triggerControl);
naibrd_AD_GetEventMappedStatusRaw(cardIndex, module, channel, NAI_STATUS_REALTIME, NAIBRD_AD_FIFO_STATUS, &fifoStatus);
naiif_printf( "\r\n %2d %-7u %-7d %-7d %-7d %-7d %-7d %-7d %-7d %-7d 0x%02X 0x%02X 0x%02X",
channel, wordsInFifo, hiThreshold, loThreshold, almostEmpty, almostFull, sampleDelay,
skipCount, fifoSize, sampleRate, bufferControl, triggerControl, fifoStatus );
}
}
static nai_status_t ADFIFO_ConfigChannel(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;
uint32_t rangeRaw = 0u, loThreshold = 0u, hiThreshold = 0u, samplesPerTrigger = 0u, sampleDelay = 0u, almostEmpty = 0u, almostFull = 0u;
uint32_t skipCount = 0u, sampleRate = 0u, bufferControl = 0u;
uint32_t maxFifoCount = 0u;
naibrd_ad_polarity_t polarity;
bool_t success = NAI_FALSE;
uint32_t modid = 0u;
float64_t range = 0.0;
uint32_t activateChannel = 0;
bool_t channelActive = NAI_TRUE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
/* Query the user for the channel number */
naiapp_query_ChannelNumber(p_ad_params->maxChannels, 1, &channel);
p_ad_params->channel = channel;
naibrd_GetModuleName(cardIndex, module, &modid);
maxFifoCount = (uint32_t)naibrd_AD_GetMaxFIFOCount(modid);
if ((modid == NAIBRD_MODULE_ID_AD4) || (modid == NAIBRD_MODULE_ID_AD5) || (modid == NAIBRD_MODULE_ID_AD5) )
{
naiif_printf("In order to use the FIFO on any channel, that channel must set ACTIVE. Inactive channels will not collect data.\r\n");
naiif_printf("Set channel %i to ACTIVE? Enter 0 for NO, any other entry will activate the channel [default: 1]>>", channel);
success = ADUtils_getInput(&activateChannel);
if ( NAI_TRUE == success )
{
channelActive = (activateChannel == 0 ? NAI_FALSE : NAI_TRUE);
}
check_status(naibrd_AD_SetActiveChannel(cardIndex, module, channel, channelActive));
}
if (channelActive)
{
do
{
ADUtils_printRangeOptions(modid, NAIBRD_AD_MODE_VOLTAGE);
naiif_printf("Please enter range/polarity in hex {default=0x10]:\r\n>>");
success = ADUtils_getInput(&rangeRaw);
if ( NAI_TRUE != success )
rangeRaw = 0x10;
success = NAI_TRUE;
} while ( !(success) || !(( rangeRaw <= 0x03) || (rangeRaw >= 0x09 && rangeRaw <= 0x0A) ||
(rangeRaw >= 0x10 && rangeRaw <= 0x13) || (rangeRaw >=0x19 && rangeRaw <= 0x1A )) );
naibrd_AD_ConvertToRange(modid, NAIBRD_AD_MODE_VOLTAGE, rangeRaw, &polarity, &range);
do
{
naiif_printf( "\r\nPlease enter low threshold (0-%d) [default=10]:\r\n>>", maxFifoCount);
success = ADUtils_getInput(&loThreshold);
if ( NAI_TRUE != success )
loThreshold = 10;
success=NAI_TRUE;
} while (!success || (loThreshold > maxFifoCount));
do
{
naiif_printf( "\r\nPlease enter high threshold (0-%d) [default=15]:\r\n>>", maxFifoCount);
success = ADUtils_getInput(&hiThreshold);
if ( NAI_TRUE != success )
hiThreshold = 15;
success= NAI_TRUE;
} while (!success || (hiThreshold > maxFifoCount));
do
{
naiif_printf( "\r\nPlease enter Almost Empty threshold (0-%d) [default=5]:\r\n>>", maxFifoCount);
success = ADUtils_getInput(&almostEmpty);
if ( NAI_TRUE != success )
almostEmpty = 5;
success = NAI_TRUE;
} while (!success || (almostFull > maxFifoCount));
do
{
naiif_printf( "\r\nPlease enter Almost Full threshold (0-%d) [default=18]:\r\n>>", maxFifoCount);
success = ADUtils_getInput(&almostFull);
if ( NAI_TRUE != success )
almostFull = 18;
success = NAI_TRUE;
} while (!success || (almostFull > maxFifoCount));
do
{
naiif_printf( "\r\nPlease enter the sample rate [default=250000]:\r\n>>");
success = ADUtils_getInput(&sampleRate);
if ( NAI_TRUE != success )
sampleRate = 250000;
success = NAI_TRUE;
} while (!success || (sampleRate > 250000));
do
{
naiif_printf( "\r\nPlease enter the delay (0-4294967295 (0xFFFFFFFF)) [default=0]:\r\n>>");
success = ADUtils_getInput(&sampleDelay);
if ( NAI_TRUE != success )
sampleDelay = 0;
success = NAI_TRUE;
} while (!success);
do
{
naiif_printf( "\r\nPlease enter the Skip Count (0-4294967295 (0xFFFFFFFF)) [default=0]:\r\n>>");
success = ADUtils_getInput(&skipCount);
if ( NAI_TRUE != success )
skipCount = 0;
success = NAI_TRUE;
} while (!success);
do
{
naiif_printf( "\r\nPlease enter the fifo size (0-%d) [default=20]:\r\n>>", maxFifoCount);
success = ADUtils_getInput(&samplesPerTrigger);
if ( NAI_TRUE != success )
samplesPerTrigger = 20;
success = NAI_TRUE;
} while (!success || (samplesPerTrigger > maxFifoCount));
do
{
ADFIFO_printBufferRequest();
success = ADUtils_getInput(&bufferControl);
if ( NAI_TRUE != success )
bufferControl = 0;
success = (bufferControl == 0 || bufferControl == 4 || bufferControl == 16 ||
bufferControl == 20);
} while (!success);
do
{
ADFIFO_printTriggerCtrlRequest();
success = ADUtils_getInput(&g_triggerControl);
if ( NAI_TRUE != success )
{
g_triggerControl = 0x130;
success = NAI_TRUE;
}
} while (!success);
check_status(naibrd_AD_SetRangePolarity(cardIndex, module, channel, polarity, range));
check_status(naibrd_AD_SetFIFOLoThreshold(cardIndex, module, channel, loThreshold));
check_status(naibrd_AD_SetFIFOHiThreshold(cardIndex, module, channel, hiThreshold));
check_status(naibrd_AD_SetFIFODelay(cardIndex, module, channel, sampleDelay));
check_status(naibrd_AD_SetFIFOSize(cardIndex, module, channel, samplesPerTrigger));
check_status(naibrd_AD_SetSampleRate(cardIndex, module, sampleRate));
check_status(naibrd_AD_SetFIFOCtrl(cardIndex, module, channel, bufferControl));
check_status(naibrd_AD_SetFIFOTrigCtrl(cardIndex, module, channel, g_triggerControl));
check_status(naibrd_AD_SetFIFOAlmostEmpty(cardIndex, module, channel, almostEmpty));
check_status(naibrd_AD_SetFIFOAlmostFull(cardIndex, module, channel, almostFull));
check_status(naibrd_AD_SetFIFOSkip(cardIndex, module, channel, skipCount));
}
return NAI_SUCCESS;
}
static nai_status_t ADFIFO_SwTrigger(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_AD_SoftwareTrigger( p_ad_params->cardIndex, p_ad_params->module));
return NAI_SUCCESS;
}
static nai_status_t ADFIFO_SwTriggerMeasTime(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;
uint32_t fifoCount = 0;
uint32_t timeout = 0;
uint32_t fifoStatus = 0;
bool_t fifoSampleDone = NAI_FALSE;
const int POLLING_DELAY_MS = 1;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
naiif_printf("Since a trigger will cause all active channels to collect data, only one of the active channels will be monitored for timing.\r\n");
naiif_printf("Which channel do you want to monitor?\r\n");
naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
naibrd_AD_SetFIFOTrigCtrl(cardIndex, module, 1, 0);
for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
{
check_status(naibrd_AD_ClearFIFO(cardIndex, module, channel));
}
naibrd_AD_SetFIFOTrigCtrl(cardIndex, module, 1, g_triggerControl);
check_status(naibrd_AD_SoftwareTrigger(cardIndex, module));
do
{
naiif_msDelay(POLLING_DELAY_MS);
check_status(naibrd_AD_GetEventMappedStatusRaw(cardIndex, module, p_ad_params->channel, NAI_STATUS_REALTIME, NAIBRD_AD_FIFO_STATUS,
(uint32_t*)&fifoStatus));
fifoSampleDone = (bool_t)(0 != (fifoStatus & NAIBRD_AD_FIFO_STATUS_DONE));
timeout += POLLING_DELAY_MS;
} while (!fifoSampleDone && (timeout <= 5000));
naibrd_AD_SetFIFOTrigCtrl(cardIndex, module, 1, 0);
check_status(naibrd_AD_GetFIFOCount(cardIndex, module, p_ad_params->channel, &fifoCount));
if (!fifoSampleDone)
naiif_printf("Sample Done timeout @ %umS!\r\n", timeout);
naiif_printf("FIFO Count %u, Elapse Time: %umS\r\n", fifoCount, timeout);
return NAI_SUCCESS;
}
static nai_status_t ADFIFO_DisplayFifoStatus(int32_t paramCount, int32_t* p_params)
{
uint32_t modid = 0u;
naibrd_ad_fifo_status_t fifoStatus = (naibrd_ad_fifo_status_t)0x0u;
int32_t maxChannels = 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;
uint32_t sampleDone = 0u, fifoFull = 0u, hiLimit = 0u, loLimit = 0u, empty = 0u, almostEmpty = 0u, almostFull = 0u;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_GetModuleName(cardIndex, module, &modid));
maxChannels = naibrd_AD_GetChannelCount(modid);
naiif_printf( "\r\n\r\n\r\n" );
naiif_printf( "| Ch | Status Register| Sample Done | FIFO Full | Hi Limit | Lo Limit | Empty | Almost | Almost |\r\n" );
naiif_printf( "| | (hex value) | | | | | | empty | full |\r\n" );
naiif_printf( "|----|----------------|-------------|-----------|----------|----------|-------|--------|--------|\r\n" );
for ( channel = 1; channel <= maxChannels; channel++ )
{
check_status(naibrd_AD_GetEventMappedStatusRaw(cardIndex, module, channel, NAI_STATUS_REALTIME, NAIBRD_AD_FIFO_STATUS, (uint32_t*)&fifoStatus));
empty = (NAIBRD_AD_FIFO_STATUS_EMPTY == (fifoStatus & NAIBRD_AD_FIFO_STATUS_EMPTY));
almostEmpty = (NAIBRD_AD_FIFO_STATUS_ALMOSTEMPTY == (fifoStatus & NAIBRD_AD_FIFO_STATUS_ALMOSTEMPTY));
loLimit = (NAIBRD_AD_FIFO_STATUS_LOWMARK == (fifoStatus & NAIBRD_AD_FIFO_STATUS_LOWMARK));
hiLimit = (NAIBRD_AD_FIFO_STATUS_HIGHMARK == (fifoStatus & NAIBRD_AD_FIFO_STATUS_HIGHMARK));
almostFull = (NAIBRD_AD_FIFO_STATUS_ALMOSTFULL == (fifoStatus & NAIBRD_AD_FIFO_STATUS_ALMOSTFULL));
fifoFull = (NAIBRD_AD_FIFO_STATUS_FULL == (fifoStatus & NAIBRD_AD_FIFO_STATUS_FULL));
sampleDone = (NAIBRD_AD_FIFO_STATUS_DONE == (fifoStatus & NAIBRD_AD_FIFO_STATUS_DONE));
naiif_printf( "| %2d | 0x%02X | %d | %d | %d | %d | %d | %d | %d |\r\n",
channel, fifoStatus, sampleDone, fifoFull, hiLimit, loLimit, empty, almostEmpty, almostFull );
}
return NAI_SUCCESS;
}
static nai_status_t ADFIFO_ClearFifo(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
check_status(naibrd_AD_ClearFIFO(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel));
return NAI_SUCCESS;
}
static void ADFIFO_GetFifoReadInfo(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_inout_samplesToRead, bool_t* p_outbufferControls)
{
uint32_t modid = 0u;
uint32_t maxCount = *p_inout_samplesToRead;
check_status(naibrd_GetModuleName(cardIndex, module, &modid));
if ((*p_inout_samplesToRead) == 0)
{
naiif_printf("FIFO buffer is empty! No words to read!\r\n");
}
else
{
*p_outbufferControls = TimestampEnabled(cardIndex, module, channel);
do
{
naiif_printf( "\r\nHow many samples would you like to read from the FIFO? Enter\r\n" );
naiif_printf( "a number less than or equal to %d:\r\n>>", maxCount);
ADUtils_getInput(p_inout_samplesToRead);
} while (*p_inout_samplesToRead == 0 || (*p_inout_samplesToRead > maxCount));
}
}
static bool_t TimestampEnabled(int32_t cardIndex, int32_t module, int32_t channel)
{
uint32_t bufferCtrl = 0u;
check_status(naibrd_AD_GetFIFOCtrl(cardIndex, module, channel, &bufferCtrl));
return (0 == (bufferCtrl & NAIBRD_AD_FIFO_CTRL_TIMESTAMP)) ? NAI_FALSE : NAI_TRUE;
}
static nai_status_t ADFIFO_PrintSamplesInFifo(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;
uint32_t modid = 0u;
float64_t range = 0.0;
naibrd_ad_polarity_t polarity;
naibrd_ad_range_polarity_t rangeRaw;
float64_t *p_data = NULL;
uint32_t samplesRead = 0u;
uint32_t dataIndex = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
uint32_t samplesToRead = 0;
bool_t timestampEnabled = NAI_FALSE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
naiapp_query_ChannelNumber(p_ad_params->maxChannels, channel, &channel);
p_ad_params->channel = channel;
check_status(naibrd_AD_GetFIFOCount(cardIndex, module, channel, &samplesToRead));
ADFIFO_GetFifoReadInfo(cardIndex, module, channel, &samplesToRead, ×tampEnabled);
check_status(naibrd_GetModuleName(cardIndex, module, &modid));
check_status(naibrd_AD_GetRangePolarity(cardIndex, module, channel, &polarity, &range));
check_status(naibrd_AD_ConvertToRangeRaw(modid, NAIBRD_AD_MODE_VOLTAGE, polarity, range, &rangeRaw));
naiif_printf( "DATA\t\tVOLTAGE\t\t" );
if(timestampEnabled)
naiif_printf( "TIME_STAMP" );
naiif_printf("\r\n");
do
{
status = naibrd_AD_ReadFIFORaw32(cardIndex, module, channel,
samplesToRead >= NAIAPP_FIFO_BUFFER_SIZE ? NAIAPP_FIFO_BUFFER_SIZE : samplesToRead,
g_dataRaw, &samplesRead);
samplesToRead -= samplesRead;
if (status != NAI_ERROR_MORE_DATA)
{
check_status(status);
}
if (timestampEnabled)
{
for (dataIndex = 0; dataIndex < samplesRead; dataIndex+=2)
{
p_data = &(g_data[dataIndex]);
check_status(naibrd_AD_ConvertToData(modid, NAIBRD_AD_MODE_VOLTAGE, rangeRaw, 1, &(g_dataRaw[dataIndex]), &p_data));
naiif_printf("0x%08X\t%+7.6f\t %d\r\n", g_dataRaw[dataIndex], g_data[dataIndex], g_dataRaw[dataIndex + 1]);
}
}
else
{
p_data = g_data;
check_status(naibrd_AD_ConvertToData(modid, NAIBRD_AD_MODE_VOLTAGE, rangeRaw, samplesRead, g_dataRaw, &p_data));
for (dataIndex = 0; dataIndex < samplesRead; dataIndex++)
{
naiif_printf("0x%08X\t%+7.6f\r\n", g_dataRaw[dataIndex], g_data[dataIndex]);
}
}
} while (samplesToRead > 0);
return NAI_SUCCESS;
}
static nai_status_t ADFIFO_PrintSamplesInFifo256(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;
uint32_t read = 0u;
uint32_t dataIndex = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
uint32_t samplesToRead = AD_MAX_ARRAY_ALLOCATON_ON_STACK32;
bool_t timestampEnabled = NAI_FALSE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
ADFIFO_GetFifoReadInfo(cardIndex, module, channel, &samplesToRead, ×tampEnabled);
status = naibrd_AD_ReadFIFO(cardIndex, module, channel, samplesToRead, g_data, &read);
if (status != NAI_ERROR_MORE_DATA)
{
check_status(status);
}
printf("Read %u fifo elements.\r\n", read);
naiif_printf( "VOLTAGE" );
if(timestampEnabled)
{
naiif_printf( "\t\tTIME_STAMP" );
samplesToRead *= 2;
}
naiif_printf("\r\n");
do
{
naiif_printf("%+7.6f\t", g_data[dataIndex]);
if (timestampEnabled)
{
dataIndex++;
naiif_printf(" %d ", g_data[dataIndex]);
}
naiif_printf("\r\n");
dataIndex++;
} while (dataIndex < read);
return NAI_SUCCESS;
}
static void ADFIFO_printBufferRequest()
{
naiif_printf( "\r\nPlease enter a value for the Buffer Control register. Refer to the\r\n" );
naiif_printf( "bit-map table below:\r\n\r\n" );
naiif_printf( "B0 = Reserved\r\n" );
naiif_printf( "B1 = Reserved\r\n" );
naiif_printf( "B2 = Filter. Filter Data (1) or non-filtered data (0)\r\n" );
naiif_printf( "B3 = Reserved\r\n" );
naiif_printf( "B4 = Time Stamp. An integer counter that counts from 0 to 65,535 and wraps\r\n" );
naiif_printf( " around when it overflows.\r\n" );
naiif_printf( "B5 = Reserved\r\n" );
naiif_printf( "B6 = Reserved\r\n" );
naiif_printf( "B7 = Reserved\r\n" );
naiif_printf( "\r\nPlease enter the Buffer Control (0,4,16,20 ?) [default=0]:\r\n>>");
}
static void ADFIFO_printTriggerCtrlRequest()
{
naiif_printf( "\r\nTrigger Control- Please refer to the bit map below:\r\n\r\n" );
naiif_printf( "B0-B1 = Trigger Type (choose one only)\r\n" );
naiif_printf( " 0xXXX0 = Continuous- data will fill the fifo to [fifo size] after a single trigger. Data will continue to be captured,\r\n" );
naiif_printf( " even when read from the fifo, until the Trigger Control is DISABLED.\r\n" );
naiif_printf( " 0xXXX1 = Single Sample- One sample will be added to the fifo per trigger. Data will not continue to be captured after\r\n" );
naiif_printf( " it is read out.\r\n");
naiif_printf( "B2-B3 = Reserved\r\n" );
naiif_printf( "B4-B5 = Trigger Edge (Choose one only)\r\n" );
naiif_printf( " 0xXX0X = RESERVED for Hardware Trigger (Positive Edge)\r\n" );
naiif_printf( " 0xXX1X = RESERVED for Hardware Trigger (Negative Edge)\r\n" );
naiif_printf( " 0xXX2X = RESERVED for Hardware Trigger (Either Edge)\r\n" );
naiif_printf( " 0xXX3X = Software Trigger\r\n" );
naiif_printf( "B6-B7 = Reserved\r\n" );
naiif_printf( "B8 = Trigger Enable (choose one only)\r\n" );
naiif_printf( " 0xX0XX = Disable/Stop Trigger\r\n" );
naiif_printf( " 0xX1XX = Enable\r\n" );
naiif_printf( "B9-B31 = Reserved\r\n" );
naiif_printf( "\r\nBy default, we will set the Trigger Control to:\r\n" );
naiif_printf( "304 (0x0130) - Continuous Sample | Software Trigger | Enable.");
naiif_printf( "Press 'Enter' to continue or enter a new value in decimal.\r\n" );
}