Sync BasicOps Sample Application (SSK 1.x)
Overview
The Sync BasicOps sample application demonstrates how to synchronize multiple AD and DA modules so they sample and generate data in lockstep, using the NAI Software Support Kit (SSK 1.x). It coordinates several modules in one card so that a single trigger starts FIFO data collection (AD) and output (DA) simultaneously, with all modules sharing a common clock. This is the foundation for coherent multi-channel, multi-module acquisition where the timing relationship between channels matters.
Synchronization in this sample has two independent dimensions, each configured per module:
- Clock sync — which module’s sample clock drives which. One module can be the master (it supplies the clock), others are slaves (they receive it). This keeps every module sampling at the same instants.
- Trigger (FIFO) sync — which module’s FIFO trigger starts which. A master trigger fans out to all slave modules so their FIFOs start together.
The sample works with any sync-capable AD or DA module: AD1–AD6, ADE/ADF/ADG, the CME/CMF/CMG combination modules, and DA1–DA5. It is a practical reference for the module-level sync API (naibrd_AD_SetModuleSyncMode() / naibrd_DA_SetModuleSyncMode()) and the FIFO API (naibrd_AD_*FIFO*() / naibrd_DA_*FIFO*()).
The seven menu commands walk through a complete synchronized-capture workflow:
| Command | Description |
|---|---|
| CS | Configure clock sync mode for a module |
| CF | Configure FIFO trigger sync mode for a module |
| CLF | Clear FIFO contents (one module or all) |
| LOAD | Load the DA FIFOs with output data |
| TRIG | Trigger the master to start FIFO I/O on master and slaves |
| STOP | Stop FIFO I/O |
| COLLECT | Read the AD FIFOs and save the data to a file |
Prerequisites
Before running this sample, make sure you have:
- An NAI board with two or more sync-capable AD/DA modules installed (synchronization is only meaningful across multiple modules).
- 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.
- Any external clock/trigger wiring in place if you intend to use the user-clock or external-trigger slave modes.
How to Run
Launch the Sync_BasicOps executable from your build output directory. On startup the application looks for a configuration file (default_Sync_BasicOps.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection and card index. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, the application discovers every module on the card and presents a configuration table plus the command menu.
Board Connection and Module Selection
Note
This startup sequence is common to all NAI sample applications. The board connection code shown here is not specific to synchronization.
The main() function follows a standard SSK 1.x startup flow. Unlike the single-module BasicOps samples, Sync BasicOps does not ask you to pick one module — it operates on every module on the selected card:
- Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. - Query the user for a card index with
naiapp_query_CardIndex(). - Retrieve the module count with
naibrd_GetModuleCount(). - Hand the card index and module count to
SyncBasicOps_run().
#if defined (__VXWORKS__)
int32_t Sync_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t moduleCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
bQuit = SyncBasicOps_run(cardIndex, moduleCount);
}
printf("Type the Enter key to exit the program: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}Important
Common connection errors you may encounter at this stage:
- No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.
- Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.
- Invalid card index — card indices are zero-based. Ensure the value you pass matches your hardware setup.
- Only one sync-capable module present — synchronization coordinates two or more modules. With a single module there is nothing to sync to.
Program Structure
Entry Point
On standard platforms the entry point is main(). On VxWorks the entry point is Sync_BasicOps() — the SSK 1.x build system selects the correct variant via a preprocessor guard:
#if defined (__VXWORKS__)
int32_t Sync_BasicOps(void)
#else
int32_t main(void)
#endifThe Sync Info Structure
SyncBasicOps_run() builds a naiapp_syncInfo_t that tracks every module on the card — its ID, its module type, the channel in use, and which module is the current trigger master. This struct is passed to every command handler:
typedef struct naiapp_syncInfo
{
int32_t cardIndex;
int32_t moduleCount;
uint32_t modId[NAI_MAX_MODULES];
syncops_module_type_t moduleType[NAI_MAX_MODULES];
int32_t triggerMasterModNum;
int32_t channel[NAI_MAX_MODULES]; /* 1 channel per module */
} naiapp_syncInfo_t;The module type is derived by masking the upper 16 bits of the module ID. Every AD module ID (AD1, AD2, …) shares the same upper half, as does every DA module ID, so a single mask classifies the module without an exhaustive ID list:
#define SYNCOPS_MOD_TYPE_MASK 0xFFFF0000u
#define SYNCOPS_MOD_TYPE_AD (NAI_MODULE_ID_AD1 & SYNCOPS_MOD_TYPE_MASK)
#define SYNCOPS_MOD_TYPE_DA (NAI_MODULE_ID_DA1 & SYNCOPS_MOD_TYPE_MASK)Per-Type API Dispatch
The module-level sync and FIFO operations exist in both an AD and a DA flavor (naibrd_AD_* and naibrd_DA_*) with matching signatures. The sample wraps each operation in a small helper that switches on the module type and calls the correct variant. For example, SetModuleSyncMode():
static nai_status_t SetModuleSyncMode(naiapp_syncInfo_t syncInfo, int32_t modNum,
naibrd_module_sync_config_type_t config, naibrd_module_sync_mode_type_t mode, int32_t masterModNum)
{
switch (syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
return naibrd_AD_SetModuleSyncMode(syncInfo.cardIndex, modNum, config, mode, masterModNum);
case SYNCOPS_MOD_TYPE_DA:
return naibrd_DA_SetModuleSyncMode(syncInfo.cardIndex, modNum, config, mode, masterModNum);
default:
return NAI_ERROR_NOT_SUPPORTED;
}
}The same pattern wraps GetModuleSyncMode(), ReadFIFO32(), SoftwareTrigger(), GetFIFOSize(), GetFIFOCount(), and GetModuleRate(). In your own application, if you know the module type up front, you can call the naibrd_AD_* or naibrd_DA_* function directly without the wrapper.
Startup: FIFO Sizing
As it builds the sync info, SyncBasicOps_run() sizes every channel’s FIFO on each sync-capable module to a fixed sample count (SYNCOPS_NUM_FIFO_SAMPLES, 100) using naibrd_AD_SetFIFOSize() / naibrd_DA_SetFIFOSize(). The FIFO size is the number of samples collected (AD) or played out (DA) per trigger:
for (channel = 1; channel <= naibrd_AD_GetChannelCount(modId); channel++)
naibrd_AD_SetFIFOSize(cardIndex, modNum, channel, SYNCOPS_NUM_FIFO_SAMPLES);Command Loop and Configuration Display
SyncBasicOps_run() then loops: it prints a configuration table for every module (SyncBasicOps_displayConfigurations()), shows the command menu, and dispatches the selected command. The configuration table reads back, per module, the clock sync mode, trigger sync mode, sample rate, FIFO size, and FIFO count — so you can watch the sync configuration change as you issue commands.
GetModuleSyncMode(syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, &clockMode, &clockMasterModNum);
GetModuleSyncMode(syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, &triggerMode, &triggerMasterModNum);
GetFIFOSize(syncInfo, modNum, channel, &numSamplesPerTrigger);
GetFIFOCount(syncInfo, modNum, channel, &fifoCount);Clock Synchronization
The Configure Clock Sync (CS) command sets a module’s clock sync mode with SetModuleSyncMode() and the NAIBRD_SYNC_CONFIG_CLOCK configuration selector. This determines where the module’s sample clock comes from. After selecting a module, you choose one of five modes:
/* Disabled: module uses its own internal clock, not synced to anything */
naibrd_AD_SetModuleSyncMode(cardIndex, modNum, NAIBRD_SYNC_CONFIG_CLOCK,
NAIBRD_MODULE_SYNC_MODE_DISABLED, 0);
/* Master: this module supplies the clock to the slaves (master = itself) */
naibrd_AD_SetModuleSyncMode(cardIndex, modNum, NAIBRD_SYNC_CONFIG_CLOCK,
NAIBRD_MODULE_SYNC_MODE_MASTER, modNum);
/* Slave, internal board: receives the clock from a master module on the same board */
naibrd_AD_SetModuleSyncMode(cardIndex, modNum, NAIBRD_SYNC_CONFIG_CLOCK,
NAIBRD_MODULE_SYNC_MODE_SLAVE_INTERNAL, masterModNum);The five clock modes are:
NAIBRD_MODULE_SYNC_MODE_DISABLED— the module runs on its own internal clock and does not sync.NAIBRD_MODULE_SYNC_MODE_MASTER— the module supplies the clock to slave modules. The master module number is itself.NAIBRD_MODULE_SYNC_MODE_SLAVE_USER_CLOCK— the module syncs to a user-supplied (external I/O) clock and passes it on to other slaves.NAIBRD_MODULE_SYNC_MODE_SLAVE_INTERNAL— the module receives its clock from a master (or user-clock) module on the same board. You are prompted for the master module number.NAIBRD_MODULE_SYNC_MODE_SLAVE_BOARD_CLOCK— the module receives a clock supplied by an off-board master.
Note
For slave-internal and slave-external modes, the sample prompts for the master module number with
GetMasterModule(). A master module number of0disables sync (used by the disabled and user-clock modes).
FIFO Trigger Synchronization
The Configure FIFO (CF) command sets a module’s trigger sync mode — which module’s FIFO trigger starts which. It calls the ConfigFifoSync() helper, which sets the trigger sync mode with SetModuleSyncMode() (using NAIBRD_SYNC_CONFIG_TRIGGER) and then programs the FIFO trigger control register with naibrd_AD_SetFIFOTrigCtrl() / naibrd_DA_SetFIFOTrigCtrl():
static nai_status_t ConfigFifoSync(naiapp_syncInfo_t *p_syncInfo, int32_t modNum,
naibrd_module_sync_mode_type_t mode, uint32_t trigCtrl)
{
SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, mode, p_syncInfo->triggerMasterModNum);
switch (p_syncInfo->moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
naibrd_AD_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, channel, (nai_ad_fifo_trig_t)trigCtrl);
break;
case SYNCOPS_MOD_TYPE_DA:
naibrd_DA_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, channel, (nai_da_fifo_trig_t)trigCtrl);
naibrd_DA_SetFIFOCtrl(p_syncInfo->cardIndex, modNum, channel,
NAI_DA_GEN5_FIFO_CTRL_REPEAT_MODE | NAI_DA_GEN5_FIFO_CTRL_ENABLE);
break;
}
/* ... */
}The trigger control bits combine a trigger source with continuous-mode and enable flags. The sample uses these combinations per mode:
- DISABLED —
NAI_AD_GEN5_FIFO_TRIG_STOP. The module is not part of the trigger chain. - MASTER —
NAI_AD_GEN5_FIFO_TRIG_SOFT | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS. The master starts on a software trigger and fans the trigger out to slaves. - SLAVE (user trigger) —
NAI_AD_GEN5_FIFO_TRIG_POS_EDGE | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS. Triggered externally, then triggers the slave chain. - SLAVE (internal trigger) —
NAI_AD_GEN5_FIFO_TRIG_POS_EDGE | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS. Triggered from the master/user-trigger module.
Note
naibrd_DA_SetFIFOCtrl()does not apply to every DA module and may returnNAI_ERROR_NOT_SUPPORTED. That is expected and harmless — the modules that do not support it do not need the setting.
Loading DA Output Data
For DA modules, the LOAD command preloads the FIFO with the waveform to play out on trigger. SyncBasicOps_loadData() first disables the FIFO trigger (so it does not start playing while loading), then writes samples with naibrd_DA_SetFIFO32():
/* Disable the FIFO trigger before loading */
naibrd_DA_GetFIFOTrigCtrl(cardIndex, modNum, channel, &trigCtrl);
trigCtrl &= ~NAI_DA_GEN5_FIFO_TRIG_ENABLE;
naibrd_DA_SetFIFOTrigCtrl(cardIndex, modNum, channel, trigCtrl);
/* Write the FIFO with data (the sample alternates between 0.0 V and 5.0 V) */
float32_t data[] = {0.0, 5.0};
for (dataIndex = 0; dataIndex < SYNCOPS_NUM_FIFO_SAMPLES; dataIndex++)
naibrd_DA_SetFIFO32(cardIndex, modNum, channel, 1,
&data[dataIndex % 2], &written);Only modules whose trigger sync mode is not disabled are loaded. AD modules are skipped — they capture rather than generate.
Triggering and Collecting Data
Trigger (TRIG)
The TRIG command starts a synchronized capture/generation. SyncBasicOps_triggerMaster() first enables the FIFO trigger on every module (SetFifoTriggers(TRUE)), then issues a single software trigger to the master with SoftwareTrigger(). Because the slaves are chained to the master, they all start together:
SetFifoTriggers(p_syncInfo, TRUE); /* arm every module's FIFO */
if (p_syncInfo->triggerMasterModNum != 0)
SoftwareTrigger(*p_syncInfo, p_syncInfo->triggerMasterModNum); /* one trigger starts all */
else
printf("Waiting for external trigger..\n");SetFifoTriggers() sets or clears the NAI_AD_GEN5_FIFO_TRIG_ENABLE / NAI_DA_GEN5_FIFO_TRIG_ENABLE bit on each module by reading the current trigger control, masking the enable bit, and writing it back.
Note
Once enabled, a FIFO keeps collecting until it reaches its configured size; if data is removed while it is still enabled it resumes collecting. The FIFO must be disabled (via STOP, or as
COLLECTdoes before reading) to access a stable snapshot of the data.
Stop (STOP)
The STOP command disables FIFO I/O on all modules by calling SetFifoTriggers(FALSE), clearing the trigger-enable bit everywhere.
Collect (COLLECT)
The COLLECT command reads the captured AD data and writes it to a file (sync_data.txt). For each AD module whose trigger sync is enabled, SyncBasicOps_collectData() disables the FIFO trigger (to freeze the data), then reads the FIFO with naibrd_AD_ReadFIFO32():
/* Freeze the FIFO */
naibrd_AD_GetFIFOTrigCtrl(cardIndex, modNum, channel, &trigCtrl);
trigCtrl &= ~NAI_AD_GEN5_FIFO_TRIG_ENABLE;
naibrd_AD_SetFIFOTrigCtrl(cardIndex, modNum, channel, trigCtrl);
/* Read all samples into fifoData[modNum-1][] */
naibrd_AD_ReadFIFO32(cardIndex, modNum, channel, SYNCOPS_NUM_FIFO_SAMPLES,
fifoData[modNum-1], &read[modNum-1]);The collected samples from every active AD module are written column-by-column to sync_data.txt, indexed by sample number, so you can line up the synchronized readings across modules.
Clearing FIFOs
The CLF command empties FIFO contents without reading them, for one module or all. SyncBasicOps_clearFifo() calls naibrd_AD_ClearFIFO() / naibrd_DA_ClearFIFO():
naibrd_AD_ClearFIFO(cardIndex, modNum, channel); /* AD module */
naibrd_DA_ClearFIFO(cardIndex, modNum, channel); /* DA module */This is useful between runs to discard stale samples before a fresh trigger.
Troubleshooting Reference
This table summarizes common errors and symptoms covered in the sections above. Consult your module’s manual for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
| No board found or connection timeout | Board not powered, incorrect or missing configuration file, network issue | Verify hardware is powered and connected. If default_Sync_BasicOps.txt exists, check that it lists the correct interface and address; otherwise configure and save your connection in the board menu. |
| Module shows “NO” under SyncSupport | The module type does not support synchronization | Synchronization is supported on AD1–AD6, ADE/ADF/ADG, CME/CMF/CMG, and DA1–DA5. Other module types are skipped. |
| Trigger does nothing / FIFOs stay empty | No module set as trigger master, or master/slave modes not configured | Configure one module as trigger MASTER and the others as SLAVE before issuing TRIG. With no master, the app waits for an external trigger. |
| Data not synchronized across modules | Clock sync not configured, only trigger sync set | Configure clock sync (CS) as well as FIFO trigger sync (CF) — both a shared clock and a shared trigger are needed for coherent data. |
NAI_ERROR_NOT_SUPPORTED from naibrd_DA_SetFIFOCtrl() | The DA module does not implement this control | Expected on some DA modules; the setting is not required for them. |
| COLLECT produces an empty/short file | FIFOs not filled (trigger not completed) or AD trigger sync disabled | Ensure the capture completed before collecting, and that the AD modules have trigger sync enabled (not disabled). |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — Sync_BasicOps.c (SSK 1.x)
#include <stdint.h>
#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"
#include "nai_ad_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ad.h"
#include "functions/naibrd_da.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.h"
static const int8_t *SAMPLE_PGM_NAME = (const int8_t *)"Synchronization Basic Operation Program";
static const int8_t *CONFIG_FILE = (const int8_t *)"default_Sync_BasicOps.txt";
static const char *DATA_FILE = (const char*)"sync_data.txt";
/* Module Type definitions. The Module type is the 16 msb of the module ID. So module ID's like AD1, AD2, AD3, etc are
all AD module types. The module ID of ANY AD module can give us the module type by masking out the
lower 16 bits and retaining the upper 16 bits. This is true for all NAI modules (AD, DA, CM, etc).
*/
#define SYNCOPS_MOD_TYPE_MASK 0xFFFF0000u
typedef uint32_t syncops_module_type_t;
#define SYNCOPS_MOD_TYPE_UNKNOWN (syncops_module_type_t)0u;
#define SYNCOPS_MOD_TYPE_AD (syncops_module_type_t)(NAI_MODULE_ID_AD1 & SYNCOPS_MOD_TYPE_MASK)
#define SYNCOPS_MOD_TYPE_DA (syncops_module_type_t)(NAI_MODULE_ID_DA1 & SYNCOPS_MOD_TYPE_MASK)
#define SYNCOPS_FIFO_TRIG_SOFT(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_SOFT : NAIBRD_DA_GEN5_FIFO_TRIG_SOFT))
#define SYNCOPS_FIFO_TRIG_POS_EDGE(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_POS_EDGE : NAIBRD_DA_GEN5_FIFO_TRIG_PSLOPE))
#define SYNCOPS_FIFO_TRIG_NEG_EDGE(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_NEG_EDGE : NAIBRD_DA_GEN5_FIFO_TRIG_NSLOPE))
#define SYNCOPS_FIFO_TRIG_EITHER_EDGE(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_EITHER_EDGE : NAIBRD_DA_GEN5_FIFO_TRIG_EITHER_SLOPE))
#define SYNCOPS_FIFO_TRIG_STOP(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_STOP : NAIBRD_DA_GEN5_FIFO_TRIG_STOP))
#define SYNCOPS_FIFO_TRIG_ENABLE(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_ENABLE : NAIBRD_DA_GEN5_FIFO_TRIG_ENABLE))
#define SYNCOPS_FIFO_TRIG_CONTINUOUS(t) ((uint32_t)(t == SYNCOPS_MOD_TYPE_AD ? NAIBRD_AD_FIFO_TRIG_CONTINUOUS : NAIBRD_DA_GEN5_FIFO_TRIG_CONTINUOUS))
/* Structure to hold sync info. */
typedef struct naiapp_syncInfo
{
int32_t cardIndex;
int32_t moduleCount;
uint32_t modId[NAI_MAX_MODULES];
syncops_module_type_t moduleType[NAI_MAX_MODULES];
int32_t triggerMasterModNum;
int32_t channel[NAI_MAX_MODULES]; /*1 channel per module. */
} naiapp_syncInfo_t;
#define SYNC_PARAM_COUNT 6
/* Function prototypes */
static bool_t SyncBasicOps_run(int32_t cardIndex, int32_t moduleCount);
static void SyncBasicOps_displayConfigurations(int32_t paramCount, naiapp_syncInfo_t *p_syncInfo);
/* AD Basic Ops Command Functions */
static nai_status_t SyncBasicOps_configClockSync(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_configFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_clearFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_triggerMaster(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_stopFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_collectData(int32_t paramCount, int32_t* p_params);
static nai_status_t SyncBasicOps_loadData(int32_t paramCount, int32_t* p_params);
/* Application Functions */
static bool_t SyncSupported(uint32_t modID);
static const char* SyncModeString(naibrd_module_sync_mode_type_t mode);
static bool_t GetMasterModule(naiapp_syncInfo_t *p_syncInfo, int32_t *p_masterModNum);
static syncops_module_type_t GetModuleType(uint32_t modID);
static nai_status_t ConfigFifoSync(naiapp_syncInfo_t *p_syncInfo, int32_t modNum, naibrd_module_sync_mode_type_t mode, uint32_t trigCtrl);
static nai_status_t SetFifoTriggers(naiapp_syncInfo_t *p_syncInfo, bool_t trigEnable);
static nai_status_t GetModuleSyncMode(naiapp_syncInfo_t syncInfo, int32_t modNum, naibrd_module_sync_config_type_t config,
naibrd_module_sync_mode_type_t *p_mode, int32_t *p_masterModNum);
static nai_status_t SetModuleSyncMode(naiapp_syncInfo_t syncInfo, int32_t modNum, naibrd_module_sync_config_type_t config,
naibrd_module_sync_mode_type_t mode, int32_t masterModNum);
static nai_status_t ReadFIFO32(naiapp_syncInfo_t syncInfo, int32_t modNum, uint32_t *p_outRead);
static nai_status_t SoftwareTrigger(naiapp_syncInfo_t syncInfo, int32_t modNum);
static nai_status_t GetFIFOSize(naiapp_syncInfo_t syncInfo, int32_t modNum, int32_t channel, uint32_t *p_fifoSize);
static nai_status_t GetFIFOCount(naiapp_syncInfo_t syncInfo, int32_t modNum, int32_t channel, uint32_t *p_fifoCount);
static nai_status_t GetModuleRate(naiapp_syncInfo_t syncInfo, int32_t modNum, uint32_t *p_rate);
#define DEFAULT_CHANNEL 1
#define SYNCOPS_NUM_FIFO_SAMPLES 100u
static float32_t fifoData[NAI_MAX_MODULES][SYNCOPS_NUM_FIFO_SAMPLES];
/****** Command Table *******/
/* Invariant: enumeration of cmd table starts from 0 and increments by 1 */
enum sync_basicOps_commands
{
SYNC_BASICOPS_CMD_CONFIG_CLOCK_SYNC, /* Configure Clock Sync */
SYNC_BASICOPS_CMD_CONFIG_FIFO, /* Configure FIFO */
SYNC_BASICOPS_CMD_CLEAR_FIFO, /* Clear FIFO */
SYNC_BASICOPS_CMD_LOAD_FIFO_DATA, /* Load the DA FIFO's with data. */
SYNC_BASICOPS_CMD_SEND_FIFO_TRIGGER, /* Trigger to start fifo i/o. */
SYNC_BASICOPS_CMD_STOP_FIFO, /* Stop fifo i/o. */
SYNC_BASICOPS_CMD_COLLECT_FIFO_DATA, /* Read the AD FIFO's and store the data to a file. */
SYNC_BASICOPS_CMD_COUNT
};
naiapp_cmdtbl_params_t Sync_BasicOpsCmds[] =
{
{"CS", "Configure Clock Sync", SYNC_BASICOPS_CMD_CONFIG_CLOCK_SYNC, SyncBasicOps_configClockSync },
{"CF", "Configure FIFO", SYNC_BASICOPS_CMD_CONFIG_FIFO, SyncBasicOps_configFifo },
{"CLF", "Clear FIFO contents", SYNC_BASICOPS_CMD_CLEAR_FIFO, SyncBasicOps_clearFifo },
{"LOAD", "Load the DA FIFO's with data.", SYNC_BASICOPS_CMD_LOAD_FIFO_DATA, SyncBasicOps_loadData },
{"TRIG", "Trigger Master to start FIFOs on the Master and Slave.", SYNC_BASICOPS_CMD_SEND_FIFO_TRIGGER, SyncBasicOps_triggerMaster },
{"STOP", "Stop fifo i/o", SYNC_BASICOPS_CMD_STOP_FIFO, SyncBasicOps_stopFifo },
{"COLLECT", "Read the AD FIFO's and store the data to a file. ", SYNC_BASICOPS_CMD_COLLECT_FIFO_DATA, SyncBasicOps_collectData }
};
/*****************************************************************************/
/**
* <summary>
* The purpose of the AD_BasicOps is to illustrate the methods to call in the
* naibrd library to perform basic operations with the AD modules for
* configuration setup and reading the channels.
*
* 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 AD routines.
* - ConfigDevice
* - DisplayDeviceCfg
* - GetBoardSNModCfg
* - CheckModule
* </summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t Sync_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t moduleCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
bQuit = SyncBasicOps_run(cardIndex, moduleCount);
}
printf("Type the Enter key to exit the program: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
/*****************************************************************************/
/**
* <summary>
* SyncBasicOps_run illustrates the channel configuration and prepares the menu
* which will handle user command requests. Returns TRUE if the user enters
* the Quit Command at any point within its scope.
* </summary>
*/
/*****************************************************************************/
static bool_t SyncBasicOps_run(int32_t cardIndex, int32_t moduleCount)
{
bool_t bQuit = FALSE;
bool_t bCmdFound = FALSE;
int32_t cmd;
naiapp_syncInfo_t syncInfo;
int32_t moduleIndex = 0;
naibrd_module_sync_mode_type_t syncMode;
int32_t triggerMasterModNum = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
int32_t channel = 0;
syncInfo.cardIndex = cardIndex;
syncInfo.moduleCount = moduleCount;
syncInfo.triggerMasterModNum = 0;
for(moduleIndex = 0; moduleIndex < moduleCount; moduleIndex++)
{
syncInfo.channel[moduleIndex] = DEFAULT_CHANNEL;
syncInfo.modId[moduleIndex] = naibrd_GetModuleID(cardIndex, moduleIndex + 1);
syncInfo.moduleType[moduleIndex] = GetModuleType(syncInfo.modId[moduleIndex]);
if (FALSE != SyncSupported(syncInfo.modId[moduleIndex]))
{
GetModuleSyncMode(syncInfo, moduleIndex + 1, NAIBRD_SYNC_CONFIG_TRIGGER, &syncMode, &triggerMasterModNum);
if (NAIBRD_MODULE_SYNC_MODE_MASTER == syncMode)
{
syncInfo.triggerMasterModNum = triggerMasterModNum;
}
switch(syncInfo.moduleType[moduleIndex])
{
case SYNCOPS_MOD_TYPE_AD:
for (channel = 1; channel <= naibrd_AD_GetChannelCount(syncInfo.modId[moduleIndex]); channel++)
{
check_status(naibrd_AD_SetFIFOSize(syncInfo.cardIndex, moduleIndex + 1, channel, SYNCOPS_NUM_FIFO_SAMPLES));
}
break;
case SYNCOPS_MOD_TYPE_DA:
for (channel = 1; channel <= naibrd_DA_GetChannelCount(syncInfo.modId[moduleIndex]); channel++)
{
check_status(naibrd_DA_SetFIFOSize(syncInfo.cardIndex, moduleIndex + 1, channel, SYNCOPS_NUM_FIFO_SAMPLES));
}
break;
default:
printf("SyncBasicOps_run-> ERROR! Unsupported Module Type %u\n", syncInfo.moduleType[moduleIndex]);
break;
}
}
}
do
{
naiapp_utils_LoadParamMenuCommands(SYNC_BASICOPS_CMD_COUNT, Sync_BasicOpsCmds);
SyncBasicOps_displayConfigurations(SYNC_PARAM_COUNT, &syncInfo);
naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_PGM_NAME);
printf("\n\nPlease enter a command or 'q' to quit:");
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)
{
Sync_BasicOpsCmds[cmd].func(SYNC_PARAM_COUNT, (int32_t*)&syncInfo);
}
else
{
printf("Invalid command entered\n");
}
}
}
} while (!bQuit);
return bQuit;
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_displayConfigurations illustrates the methods to call in the naibrd library
* to retrieve the basic operation configuration states and status states
* as well as the current voltage reading for all channels.
* </summary>
*/
/*****************************************************************************/
static void SyncBasicOps_displayConfigurations(int32_t paramCount, naiapp_syncInfo_t* p_syncInfo)
{
int32_t modNum = 0;
naibrd_module_sync_mode_type_t clockMode = NAIBRD_MODULE_SYNC_MODE_DISABLED;
int32_t clockMasterModNum = 0;
naibrd_module_sync_mode_type_t triggerMode = NAIBRD_MODULE_SYNC_MODE_DISABLED;
int32_t triggerMasterModNum = 0;
uint32_t numSamplesPerTrigger = 0u;
uint32_t fifoCount = 0;
uint32_t rate = 0;
char szModID[] = "/0/0/0/0";
if (SYNC_PARAM_COUNT == paramCount)
{
printf("\n\n\n");
printf("------Module Info------ --------SyncClockConfig--------- --------SyncTriggerConfig------- --------------FIFO Setup--------------\n");
printf(" ModNum ID SyncSupport Mode MasterModNum Mode MasterModNum Rate Channel NumSamples FifoCount\n");
printf("-----------------------------------------------------------------------------------------------------------------------------------------\n");
for (modNum = 1; modNum <= p_syncInfo->moduleCount; modNum++)
{
naiapp_utils_ConvertModIdToAscii(p_syncInfo->modId[modNum-1], szModID);
if (FALSE != SyncSupported(p_syncInfo->modId[modNum-1]))
{
GetModuleRate(*p_syncInfo, modNum, &rate);
GetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, &clockMode, &clockMasterModNum);
GetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, &triggerMode, &triggerMasterModNum);
GetFIFOSize(*p_syncInfo, modNum, p_syncInfo->channel[modNum-1], &numSamplesPerTrigger);
GetFIFOCount(*p_syncInfo, modNum, p_syncInfo->channel[modNum-1], &fifoCount);
printf(" %d %s YES %-25s %d %-25s %d %-9d %-2d %3u %u\r\n", modNum, szModID,
SyncModeString(clockMode), clockMasterModNum, SyncModeString(triggerMode), triggerMasterModNum, rate, p_syncInfo->channel[modNum-1],
numSamplesPerTrigger, fifoCount);
}
else
{
printf(" %d %s NO --- --- --- --- --- --- --- ---\r\n",
modNum, szModID);
}
}
}
}
/*****************************************************************************/
/**
* <summary>
* ADBasicOps_setRangePolarity handles the user request to set the configuration states
* of Range and Polarity for the selected channel.
* </summary>
*/
/*****************************************************************************/
nai_status_t SyncBasicOps_configClockSync(int32_t paramCount, int32_t* p_params)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
naiapp_syncInfo_t* p_syncInfo = (naiapp_syncInfo_t*)p_params;
int32_t modNum = 0;
int32_t masterModNum = 0;
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int32_t modeSelect = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (SYNC_PARAM_COUNT == paramCount)
{
while (bContinue)
{
printf("Select module to configure (1-%d): ", p_syncInfo->moduleCount);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt >= 0)
{
modNum = (int32_t)atol((const char*)inputBuffer);
}
if ((modNum <= 0) || (modNum > p_syncInfo->moduleCount))
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
else
{
bContinue = FALSE;
}
}
else
{
bContinue = FALSE;
}
}
if (!bQuit)
{
bContinue = TRUE;
while(bContinue)
{
printf("\n\nPlease select Clock Sync Mode for this module:\n");
printf(" 0) DISABLED: This module uses its internal clock and does not sync with other modules.\n");
printf(" 1) MASTER: This module supplies the clock to other slave modules.\n");
printf(" 2) SLAVE- USER CLOCK: This module syncs with a user supplied clock and supplies it to other slave modules.\n");
printf(" 3) SLAVE- INTERNAL CLOCK: This module receives the clock from a MASTER/USER CLOCK module.\n");
printf(" 4) SLAVE- EXTERNAL BOARD CLOCK: This module receives the clock that is supplied by an off-board master.\n");
printf("\n\nPlease enter your selection: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
modeSelect = (int32_t)atol((const char*)inputBuffer);
bContinue = FALSE;
switch (modeSelect)
{
case 0:
masterModNum = 0; /* 0 disables. */
status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, NAIBRD_MODULE_SYNC_MODE_DISABLED, masterModNum);
break;
case 1:
masterModNum = modNum; /* Master gets the clock from itself. */
status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, NAIBRD_MODULE_SYNC_MODE_MASTER, masterModNum);
break;
case 2:
masterModNum = 0; /* 0 disables. */
status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, NAIBRD_MODULE_SYNC_MODE_SLAVE_USER_CLOCK, masterModNum);
break;
case 3:
bQuit = GetMasterModule(p_syncInfo, &masterModNum);
status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, NAIBRD_MODULE_SYNC_MODE_SLAVE_INTERNAL, masterModNum);
break;
case 4:
bQuit = GetMasterModule(p_syncInfo, &masterModNum);
status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_CLOCK, NAIBRD_MODULE_SYNC_MODE_SLAVE_BOARD_CLOCK, masterModNum);
break;
default:
printf("ERROR: Invalid module value.\r\n\r\n");
bContinue = TRUE;
break;
}
}
else
{
printf("ERROR: Invalid module value.\r\n\r\n");
bContinue = TRUE;
}
}
else
{
bContinue = FALSE;
}
}
}
}
return status;
}
nai_status_t SyncBasicOps_configFifo(int32_t paramCount, int32_t* p_params)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
naiapp_syncInfo_t* p_syncInfo = (naiapp_syncInfo_t*)p_params;
int32_t modNum = 0;
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int32_t modeSelect = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (SYNC_PARAM_COUNT == paramCount)
{
while (bContinue)
{
printf("Select module to configure (1-%d): ", p_syncInfo->moduleCount);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt >= 0)
{
modNum = (int32_t)atol((const char*)inputBuffer);
}
if ((modNum <= 0) || (modNum > p_syncInfo->moduleCount))
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
else
{
bContinue = FALSE;
}
}
else
{
bContinue = FALSE;
}
}
if (!bQuit)
{
bContinue = TRUE;
while(bContinue)
{
printf("\n\nPlease select FIFO Trigger Sync Mode for this module:\n");
printf(" 0) DISABLED: This module uses its internal FIFO Trigger and does not sync with other modules.\n");
printf(" 1) MASTER: This module supplies the FIFO Trigger to other slave modules.\n");
printf(" 2) SLAVE- USER TRIGGER: This module's FIFO is triggered externally and triggers the FIFOs on slave modules.\n");
printf(" 3) SLAVE- INTERNAL TRIGGER: This module's FIFO is triggered from a MASTER/USER TRIGGER module.\n");
/*printf(" 4) SLAVE- EXTERNAL BOARD TRIGGER: This module's FIFO is triggered by an off-board master.\n");*/
printf("\n\nPlease enter your selection: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
modeSelect = (int32_t)atol((const char*)inputBuffer);
bContinue = FALSE;
switch (modeSelect)
{
case 0:
p_syncInfo->triggerMasterModNum = 0; /* 0 disables. */
status = ConfigFifoSync(p_syncInfo, modNum, NAIBRD_MODULE_SYNC_MODE_DISABLED, (uint32_t)NAI_AD_GEN5_FIFO_TRIG_STOP);
break;
case 1:
p_syncInfo->triggerMasterModNum = modNum; /* Master gets the clock from itself. */
status = ConfigFifoSync(p_syncInfo, modNum, NAIBRD_MODULE_SYNC_MODE_MASTER,
(uint32_t)(NAI_AD_GEN5_FIFO_TRIG_SOFT | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS));
break;
case 2:
p_syncInfo->triggerMasterModNum = 0; /* 0 disables. */
status = ConfigFifoSync(p_syncInfo, modNum, NAIBRD_MODULE_SYNC_MODE_SLAVE_USER_CLOCK,
(uint32_t)(NAI_AD_GEN5_FIFO_TRIG_POS_EDGE | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS));
break;
case 3:
bQuit = GetMasterModule(p_syncInfo, &(p_syncInfo->triggerMasterModNum));
status = ConfigFifoSync(p_syncInfo, modNum, NAIBRD_MODULE_SYNC_MODE_SLAVE_INTERNAL,
(uint32_t)(NAI_AD_GEN5_FIFO_TRIG_POS_EDGE | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS));
break;
/*
case 4:
bQuit = GetMasterModule(p_syncInfo, &(p_syncInfo->triggerMasterModNum));
status = ConfigFifoSync(p_syncInfo, modNum, NAIBRD_MODULE_SYNC_MODE_SLAVE_BOARD_CLOCK,
(uint32_t)(NAI_AD_GEN5_FIFO_TRIG_POS_EDGE | NAI_AD_GEN5_FIFO_TRIG_CONTINUOUS));
break;
*/
default:
printf("ERROR: Invalid module value.\r\n\r\n");
bContinue = TRUE;
break;
}
naiapp_query_ChannelNumber(p_syncInfo->moduleCount, DEFAULT_CHANNEL, &(p_syncInfo->channel[modNum-1]));
}
else
{
printf("ERROR: Invalid module value.\n\n");
bContinue = TRUE;
}
}
else
{
bContinue = FALSE;
}
}
}
}
return status;
}
static nai_status_t SyncBasicOps_clearFifo(int32_t paramCount, int32_t* p_params)
{
naiapp_syncInfo_t *p_syncInfo = (naiapp_syncInfo_t*)p_params;
nai_status_t status = NAI_ERROR_UNKNOWN;
bool_t bQuit = FALSE;
int32_t startMod = 0;
int32_t endMod = 0;
int32_t modNum = 0;
bool_t bContinue = TRUE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (SYNC_PARAM_COUNT == paramCount)
{
while(bContinue)
{
printf("Please enter the module number of the FIFO to clear, or 'A' to clear all FIFOs [1-%d,A]:", p_syncInfo->moduleCount);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
if (inputBuffer[0] == 'A' || inputBuffer[0] == 'a')
{
startMod = 1;
endMod = p_syncInfo->moduleCount;
bContinue = FALSE;
}
else
{
startMod = endMod = (int32_t)atol((const char*)inputBuffer);
if ((endMod <= 0) || (endMod > p_syncInfo->moduleCount)
|| !SyncSupported(naibrd_GetModuleID(p_syncInfo->cardIndex, endMod)))
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
else
{
bContinue = FALSE;
}
}
}
else
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
}
}
if (!bQuit)
{
for(modNum = startMod; modNum <= endMod; modNum++)
{
switch(p_syncInfo->moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_ClearFIFO(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1]));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_ClearFIFO(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1]));
break;
default:
break;
}
}
}
}
return status;
}
nai_status_t SyncBasicOps_triggerMaster(int32_t paramCount, int32_t* p_params)
{
naiapp_syncInfo_t *p_syncInfo = (naiapp_syncInfo_t*)p_params;
nai_status_t status = NAI_ERROR_UNKNOWN;
uint32_t samplesToCollect = 0u;
if (SYNC_PARAM_COUNT == paramCount)
{
/* Enable the fifo's to collect data. Once enabled, fifo's will continue to collect until they reach FIFOSize. If data is
removed from the fifo while it's enabled, the fifo will begin collecting again until it reaches FIFOSize. The fifo needs
to be disabled after the collection in order to access the data without collecting more. */
SetFifoTriggers(p_syncInfo, TRUE);
if (0 != p_syncInfo->triggerMasterModNum)
{
printf("Triggering FIFO on MASTER module %d (all slaves will trigger as well)...", p_syncInfo->triggerMasterModNum);
status = SoftwareTrigger(*p_syncInfo, p_syncInfo->triggerMasterModNum);
printf("Trigger Complete. FIFO is collecting data.\n");
printf("Waiting for FIFO I/O to complete...");
GetFIFOSize(*p_syncInfo, p_syncInfo->triggerMasterModNum, p_syncInfo->channel[p_syncInfo->triggerMasterModNum - 1], &samplesToCollect);
/* Keep checking the fifo count of the master until it is equal to FifoSize(numSamplesPerTrigger). All slave fifos will collect
data at the same rate, so only check one module (in this case the master) to see when data collection is complete. */
}
else
{
printf("Waiting for external trigger..\n");
}
}
return status;
}
static nai_status_t SyncBasicOps_stopFifo(int32_t paramCount, int32_t* p_params)
{
return paramCount == SYNC_PARAM_COUNT ? SetFifoTriggers((naiapp_syncInfo_t*)p_params, FALSE) : NAI_ERROR_INVALID_VALUE;
}
static nai_status_t SyncBasicOps_loadData(int32_t paramCount, int32_t* p_params)
{
naiapp_syncInfo_t *p_syncInfo = (naiapp_syncInfo_t*)p_params;
int32_t modNum = 0;
naibrd_module_sync_mode_type_t mode;
int32_t masterModNum = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
int32_t dataIndex = 0;
float32_t data[] = {0.0, 5.0};
uint32_t written = 0;
nai_da_fifo_trig_t trigCtrl = (nai_da_fifo_trig_t)0;
if (SYNC_PARAM_COUNT == paramCount)
{
for (modNum = 1; modNum <= p_syncInfo->moduleCount; modNum++)
{
if (SYNCOPS_MOD_TYPE_DA == p_syncInfo->moduleType[modNum-1])
{
status = GetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, &mode, &masterModNum);
if (NAIBRD_MODULE_SYNC_MODE_DISABLED != mode)
{
/* Disable the fifo to stop it from sending data. */
status = check_status(naibrd_DA_GetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1], &trigCtrl));
trigCtrl &= ~NAI_DA_GEN5_FIFO_TRIG_ENABLE;
status = check_status(naibrd_DA_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1],trigCtrl));
/* Load the fifo with data. */
for (dataIndex = 0; (dataIndex < SYNCOPS_NUM_FIFO_SAMPLES) && (status == NAI_SUCCESS); dataIndex++)
{
status = check_status(naibrd_DA_SetFIFO32(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1], 1, &(data[dataIndex%(sizeof(data) / sizeof(data[0]))]), &written));
}
}
else
{
printf("Sync mode is disabled for this module.\r\n");
}
}
}
}
return status;
}
nai_status_t SyncBasicOps_collectData(int32_t paramCount, int32_t* p_params)
{
naiapp_syncInfo_t *p_syncInfo = (naiapp_syncInfo_t*)p_params;
int32_t modNum = 0;
naibrd_module_sync_mode_type_t mode;
int32_t masterModNum = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
int32_t dataIndex = 0;
char line[500];
char tmpString[50];
uint32_t read[NAI_MAX_MODULES];
FILE *dataFile = fopen(DATA_FILE, "w");
nai_ad_fifo_trig_t trigCtrl = (nai_ad_fifo_trig_t)0;
if (SYNC_PARAM_COUNT == paramCount)
{
if (NULL == dataFile)
{
printf("Can not open file %s\n", DATA_FILE);
}
else
{
memset(read, 0, sizeof(read));
/* loop through all modules and save the fifo data on the modules that are not disabled (some mode of sync enabled). */
sprintf(line, "%s", "Index ");
for (modNum = 1; modNum <= p_syncInfo->moduleCount; modNum++)
{
if (SYNCOPS_MOD_TYPE_AD == p_syncInfo->moduleType[modNum-1])
{
status = GetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, &mode, &masterModNum);
if (NAIBRD_MODULE_SYNC_MODE_DISABLED != mode)
{
/* Disable the fifo to stop it from collecting data. */
status = check_status(naibrd_AD_GetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1], &trigCtrl));
trigCtrl &= ~NAI_AD_GEN5_FIFO_TRIG_ENABLE;
status = check_status(naibrd_AD_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1], trigCtrl));
/* read the data that is in the A/D fifo. */
status = ReadFIFO32(*p_syncInfo, modNum, &(read[modNum-1]));
if (NAI_SUCCESS == status)
{
sprintf(tmpString, "Module%-6d", modNum);
strcat(line, tmpString);
}
}
}
}
fprintf(dataFile, "%s\n", line);
for(dataIndex = 0; dataIndex < SYNCOPS_NUM_FIFO_SAMPLES; dataIndex++)
{
sprintf(line, "%3u ", dataIndex);
for (modNum = 1; modNum < NAI_MAX_MODULES; modNum++)
{
if (read[modNum-1] > 0)
{
sprintf(tmpString, "%12.3f", fifoData[modNum-1][dataIndex]);
strcat(line, tmpString);
}
}
fprintf(dataFile, "%s\n", line);
line[0] = '\0';
}
fclose(dataFile);
printf("Data saved to %s\n", DATA_FILE);
}
}
return status;
}
const char* SyncModeString(naibrd_module_sync_mode_type_t mode)
{
const char* retVal = NULL;
switch(mode)
{
case NAIBRD_MODULE_SYNC_MODE_DISABLED:
retVal = "DISABLED";
break;
case NAIBRD_MODULE_SYNC_MODE_SLAVE_INTERNAL:
retVal = "SLAVE (INTERNAL BOARD)";
break;
case NAIBRD_MODULE_SYNC_MODE_SLAVE_BOARD_CLOCK:
retVal = "SLAVE (EXT BOARD SOURCE)";
break;
case NAIBRD_MODULE_SYNC_MODE_SLAVE_USER_CLOCK:
retVal = "SLAVE (EXT I/O SOURCE)";
break;
case NAIBRD_MODULE_SYNC_MODE_MASTER:
retVal = "MASTER";
break;
default:
retVal = "ERROR!";
break;
}
return retVal;
}
static bool_t SyncSupported(uint32_t modID)
{
bool_t retVal = FALSE;
switch(modID)
{
case NAI_MODULE_ID_AD1:
case NAI_MODULE_ID_AD2:
case NAI_MODULE_ID_AD3:
case NAI_MODULE_ID_AD4:
case NAI_MODULE_ID_AD5:
case NAI_MODULE_ID_AD6:
case NAI_MODULE_ID_ADE:
case NAI_MODULE_ID_ADF:
case NAI_MODULE_ID_ADG:
case NAI_MODULE_ID_CME:
case NAI_MODULE_ID_CMF:
case NAI_MODULE_ID_CMG:
case NAI_MODULE_ID_DA1:
case NAI_MODULE_ID_DA2:
case NAI_MODULE_ID_DA3:
case NAI_MODULE_ID_DA4:
case NAI_MODULE_ID_DA5:
retVal = TRUE;
break;
default:
retVal = FALSE;
break;
}
return retVal;
}
static syncops_module_type_t GetModuleType(uint32_t modID)
{
return (syncops_module_type_t)(modID & SYNCOPS_MOD_TYPE_MASK);
}
static bool_t GetMasterModule(naiapp_syncInfo_t *p_syncInfo, int32_t *p_masterModNum)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while(bContinue)
{
printf("Enter the module to sync to (master module) [1-%d]\n", p_syncInfo->moduleCount);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
*p_masterModNum = (int32_t)atol((const char*)inputBuffer);
if ((*p_masterModNum <= 0) || (*p_masterModNum > p_syncInfo->moduleCount)
|| !SyncSupported(naibrd_GetModuleID(p_syncInfo->cardIndex, *p_masterModNum)))
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
else
bContinue = FALSE;
}
else
{
printf("ERROR: Invalid module value.\r\n\r\n");
}
}
}
return bQuit;
}
static nai_status_t ConfigFifoSync(naiapp_syncInfo_t *p_syncInfo, int32_t modNum, naibrd_module_sync_mode_type_t mode, uint32_t trigCtrl)
{
nai_status_t status = SetModuleSyncMode(*p_syncInfo, modNum, NAIBRD_SYNC_CONFIG_TRIGGER, mode, p_syncInfo->triggerMasterModNum);
switch(p_syncInfo->moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1],
(nai_ad_fifo_trig_t)trigCtrl));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1],
(nai_da_fifo_trig_t)trigCtrl));
/* This API does not apply to all DA's, and may return NAAI_ERROR_NOT_SUPPORTED. This is ok because this setting is not needed by
the modules that do not support it. */
naibrd_DA_SetFIFOCtrl(p_syncInfo->cardIndex, modNum, p_syncInfo->channel[modNum-1],
NAI_DA_GEN5_FIFO_CTRL_REPEAT_MODE | NAI_DA_GEN5_FIFO_CTRL_ENABLE);
break;
default:
status = NAI_ERROR_INVALID_MODULE;
break;
}
return status;
}
static nai_status_t SetFifoTriggers(naiapp_syncInfo_t *p_syncInfo, bool_t trigEnable)
{
int32_t modIndex = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
uint32_t trigCtrl = 0u;
for(modIndex = 0; modIndex < p_syncInfo->moduleCount; modIndex++)
{
switch(p_syncInfo->moduleType[modIndex])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_GetFIFOTrigCtrl(p_syncInfo->cardIndex, modIndex + 1, p_syncInfo->channel[modIndex],
(nai_ad_fifo_trig_t*)(&trigCtrl)));
if (FALSE != trigEnable)
{
trigCtrl |= (uint32_t)NAI_AD_GEN5_FIFO_TRIG_ENABLE;
}
else
{
trigCtrl &= (uint32_t)~NAI_AD_GEN5_FIFO_TRIG_ENABLE;
}
status = check_status(naibrd_AD_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modIndex + 1, p_syncInfo->channel[modIndex],
(nai_ad_fifo_trig_t)(trigCtrl)));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_GetFIFOTrigCtrl(p_syncInfo->cardIndex, modIndex + 1, p_syncInfo->channel[modIndex],
(nai_da_fifo_trig_t*)(&trigCtrl)));
if (FALSE != trigEnable)
{
trigCtrl |= (uint32_t)NAI_DA_GEN5_FIFO_TRIG_ENABLE;
}
else
{
trigCtrl &= (uint32_t)~NAI_DA_GEN5_FIFO_TRIG_ENABLE;
}
status = check_status(naibrd_DA_SetFIFOTrigCtrl(p_syncInfo->cardIndex, modIndex + 1, p_syncInfo->channel[modIndex],
(nai_da_fifo_trig_t)(trigCtrl)));
break;
default:
break;
}
}
return status;
}
static nai_status_t GetModuleSyncMode(naiapp_syncInfo_t syncInfo, int32_t modNum, naibrd_module_sync_config_type_t config,
naibrd_module_sync_mode_type_t *p_mode, int32_t *p_masterModNum)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_GetModuleSyncMode(syncInfo.cardIndex, modNum, config, p_mode, p_masterModNum));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_GetModuleSyncMode(syncInfo.cardIndex, modNum, config, p_mode, p_masterModNum));
break;
default:
status = NAI_ERROR_NOT_SUPPORTED;
break;
}
return status;
}
static nai_status_t SetModuleSyncMode(naiapp_syncInfo_t syncInfo, int32_t modNum, naibrd_module_sync_config_type_t config,
naibrd_module_sync_mode_type_t mode, int32_t masterModNum)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_SetModuleSyncMode(syncInfo.cardIndex, modNum, config, mode, masterModNum));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_SetModuleSyncMode(syncInfo.cardIndex, modNum, config, mode, masterModNum));
break;
default:
status = NAI_ERROR_NOT_SUPPORTED;
break;
}
return status;
}
static nai_status_t ReadFIFO32(naiapp_syncInfo_t syncInfo, int32_t modNum, uint32_t *p_outRead)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_ReadFIFO32(syncInfo.cardIndex, modNum, syncInfo.channel[modNum-1], SYNCOPS_NUM_FIFO_SAMPLES,
fifoData[modNum-1], p_outRead));
break;
default:
status = NAI_ERROR_INVALID_MODULE;
*p_outRead = 0;
break;
}
return status;
}
static nai_status_t SoftwareTrigger(naiapp_syncInfo_t syncInfo, int32_t modNum)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_SoftwareTrigger(syncInfo.cardIndex, modNum));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_SoftwareTrigger(syncInfo.cardIndex, modNum));
break;
default:
status = NAI_ERROR_INVALID_MODULE;
break;
}
return status;
}
static nai_status_t GetFIFOSize(naiapp_syncInfo_t syncInfo, int32_t modNum, int32_t channel, uint32_t *p_fifoSize)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_GetFIFOSize(syncInfo.cardIndex, modNum, channel, p_fifoSize));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_GetFIFOSize(syncInfo.cardIndex, modNum, channel, p_fifoSize));
break;
default:
status = NAI_ERROR_INVALID_MODULE;
break;
}
return status;
}
static nai_status_t GetFIFOCount(naiapp_syncInfo_t syncInfo, int32_t modNum, int32_t channel, uint32_t *p_fifoCount)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_GetFIFOCount(syncInfo.cardIndex, modNum, channel, p_fifoCount));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_GetFIFOCount(syncInfo.cardIndex, modNum, channel, p_fifoCount));
break;
default:
status = NAI_ERROR_INVALID_MODULE;
break;
}
return status;
}
static nai_status_t GetModuleRate(naiapp_syncInfo_t syncInfo, int32_t modNum, uint32_t *p_rate)
{
nai_status_t status = NAI_ERROR_UNKNOWN;
switch(syncInfo.moduleType[modNum-1])
{
case SYNCOPS_MOD_TYPE_AD:
status = check_status(naibrd_AD_GetSampleRate(syncInfo.cardIndex, modNum, p_rate));
break;
case SYNCOPS_MOD_TYPE_DA:
status = check_status(naibrd_DA_GetFIFORate(syncInfo.cardIndex, modNum, 1, p_rate));
break;
default:
status = NAI_ERROR_INVALID_MODULE;
break;
}
return status;
}