RG Interrupts
Edit this on GitLab
RG Interrupts Sample Application (SSK 1.x)
Overview
The RG Interrupts sample application demonstrates how to configure and handle hardware interrupts on IRIG timecode (RG) modules using the NAI Software Support Kit (SSK 1.x). The sample configures an event-mapped interrupt on a BIT (Built-In Test) data loss condition and monitors for that condition in a continuous loop. It supports two interrupt delivery modes controlled by a compile-time flag: ISR mode (hardware interrupt with an installed callback) and polling mode (software polling of latched status registers). Both modes use the same underlying module configuration.
This sample supports the RG1 module type.
IRIG modules expose a broad range of event-mapped interrupt status types organized into two categories:
-
BIT category — hardware health conditions:
-
NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED/_REALTIME— IRIG data stream lost -
NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_LATCHED/_REALTIME— soft fault detected by self-test
-
-
General category — sync, timing, and signal events:
-
NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED/_REALTIME— reference signal lost -
NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_LATCHED/_REALTIME— reference signal received -
NAIBRD_IRIG_EVTMAP_STATUS_REF_PULSE_RX_LATCHED/_REALTIME— reference pulse received -
NAIBRD_IRIG_EVTMAP_STATUS_INTERRUPT_1PPS_OUTPUT_HIGH_LATCHED/_REALTIME— 1PPS output high -
NAIBRD_IRIG_EVTMAP_STATUS_RX_CONTROL_BITS_CHANGED_LATCHED/_REALTIME— received control bits changed -
NAIBRD_IRIG_EVTMAP_STATUS_CONTROL_BITS_RX_LATCHED/_REALTIME— control bits received -
NAIBRD_IRIG_EVTMAP_STATUS_CHANGE_REF_SRC_LATCHED/_REALTIME— reference source changed -
NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_LATCHED/_REALTIME— time event detected -
NAIBRD_IRIG_EVTMAP_STATUS_USER_INTERRUPT_LATCHED/_REALTIME— user-triggered interrupt -
NAIBRD_IRIG_EVTMAP_STATUS_DST_ADJUST_LATCHED/_REALTIME— daylight saving time adjustment -
NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_LATCHED/_REALTIME— test interrupt
-
As shipped, the sample monitors only NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED on channel 1. To monitor additional status types or channels, extend the type[] and vector[] arrays at the top of the source file. The same four-step configuration pattern (trigger type, vector, steering, enable) applies to every status type listed above.
For basic IRIG channel configuration (time format, reference source, free-run mode), see the RG BasicOps sample application guide. For background on interrupt concepts — including edge vs. level triggering, interrupt vector numbering, and steering architecture — see the Interrupts API Guide.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an IRIG module installed (RG1).
-
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.
-
To use ISR mode: compile with the
RUN_ISRpreprocessor macro defined.
How to Run
Launch the RG_Interrupts executable from your build output directory. On startup the application looks for a configuration file (default_RGInterrupts.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, the application configures interrupt monitoring on channel 1 and enters a continuous wait loop, printing each interrupt event as it is detected.
To select interrupt delivery mode, rebuild with or without the RUN_ISR preprocessor define:
-
RUN_ISRdefined — the application installs a hardware ISR vianaibrd_InstallISR(). The ISR fires when the configured status condition occurs, and the main loop processes the event. -
RUN_ISRnot defined (default) — the application polls the latched status register on each loop iteration usingnaibrd_IRIG_GetEventMappedStatus(). No ISR is installed.
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 IRIG. For details on board connection configuration, see the First Time Setup Guide. |
The main() function follows the standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file or present the interactive board menu. The configuration file (default_RGInterrupts.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 card index with
naiapp_query_CardIndex(). -
Query the user for module number with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()to verify an IRIG module is installed at the selected slot. -
Call
Run_IRIG_Interrupts()to configure and monitor interrupts.
#if defined (__VXWORKS__)
int32_t RG_Interrupts(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_IRIG_Interrupts(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;
}
Unlike many other interrupt samples, this application does not use a separate configuration structure. The card index, module number, and module ID are passed directly to Run_IRIG_Interrupts() as function arguments.
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
The RG Interrupts sample is contained in a single source file (RG_Interrupts.c). Unlike the multi-file interrupt samples for other module types, all configuration, ISR, polling, and event handling logic lives in one file.
Entry Point
main() (or RG_Interrupts() on VxWorks) handles the board connection and module selection loop described above, then calls Run_IRIG_Interrupts().
Global State
The application uses global volatile variables to communicate between the ISR (or polling function) and the main processing loop:
volatile uint32_t irqIRIGCount = 0;
volatile static uint8_t isrLock = 0;
volatile static uint32_t receivedVector = 0;
volatile static nai_status_bit_t receivedChannelStatus = 0;
volatile static naibrd_irig_event_mapped_status_type_t receivedType =
NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
volatile static interrupt_status_type_t interruptStatus = INTERRUPT_WAITING;
-
irqIRIGCount— running count of interrupts received. -
isrLock— simple lock flag. The main loop skips processing while the ISR is writing to shared variables. -
receivedVector— the interrupt vector reported by the most recent event. -
receivedChannelStatus— the latched status value read after the interrupt. -
receivedType— the event-mapped status type that triggered the interrupt. -
interruptStatus— tracks the current state:INTERRUPT_WAITING,INTERRUPT_RECEIVED, orINTERRUPT_ERROR_UNEXPECTED_VECTOR.
Interrupt Configuration Arrays
The type[] and vector[] arrays define which status types and interrupt vectors to configure. As shipped, only one entry is active:
const static naibrd_irig_event_mapped_status_type_t type[] = {
NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED
};
const static uint32_t vector[] = {
IRIG_CHANNEL1_INTERRUPT_VECTOR /* 0x000000A1u */
};
To monitor additional conditions, add entries to both arrays. Each entry in type[] pairs with the corresponding entry in vector[]. For example, to also monitor reference loss, you would add NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED to type[] and a unique vector value to vector[].
Interrupt Configuration
The Setup_IRIG_Interrupts() function configures a single event-mapped interrupt status type on channel 1. The same four-step sequence applies to every IRIG interrupt type.
Step 1: Determine the Category Type
IRIG event-mapped interrupts are organized into two categories, and you must specify the correct category when setting the vector and steering. The function maps the status type to its category with a switch statement:
naibrd_irig_event_mapped_category_type_t categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
switch (type)
{
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_REALTIME:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
break;
case NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED:
/* ... all General-category status types ... */
case NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_REALTIME:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_GENERAL;
break;
default:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
break;
}
When you add a new status type to the type[] array, this mapping ensures the correct category is used for vector and steering configuration. BIT-related types use NAIBRD_IRIG_EVTMAP_CATEGORY_BIT; all other types (sync, timing, signal events) use NAIBRD_IRIG_EVTMAP_CATEGORY_GENERAL.
Step 2: Set Trigger Type
Configure whether the interrupt fires on a status transition (edge) or remains asserted while the condition is active (level):
check_status(naibrd_IRIG_SetEventMappedInterruptTriggerType(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, type, NAIBRD_IRIG_EDGE_INTERRUPT));
The sample uses NAIBRD_IRIG_EDGE_INTERRUPT, which fires once when the condition is first detected. For BIT data loss, edge triggering is appropriate — you want to be notified when the condition occurs, not continuously while the signal is absent. For conditions you need to track as long as they persist (such as ongoing reference loss), consider using level triggering instead. See the Interrupts API Guide for a detailed comparison.
Step 3: Set Interrupt Vector
Assign a vector value that identifies this interrupt source. The vector is passed to the ISR when the interrupt fires:
check_status(naibrd_IRIG_SetEventMappedInterruptVector(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, categoryType, vector));
The vector is set per category, not per individual status type. All status types within the same category on the same channel share a single vector. The sample uses 0x000000A1 for channel 1. If you need to distinguish between multiple channels, assign a unique vector per channel.
Step 4: Set Interrupt Steering and Enable
Configure how the interrupt signal is routed to your application, then enable the interrupt:
check_status(naibrd_IRIG_SetEventMappedInterruptSteering(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, categoryType, NAIBRD_INT_STEERING_CPCI_APP));
check_status(naibrd_IRIG_SetEventMappedInterruptEnable(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, type, TRUE));
The sample steers interrupts to the cPCI backplane (NAIBRD_INT_STEERING_CPCI_APP). Modify the steering parameter to match your hardware configuration:
-
NAIBRD_INT_STEERING_ON_BOARD_0— handled locally on the board’s processor. -
NAIBRD_INT_STEERING_CPCI_APP— routed to the CompactPCI backplane host. -
NAIBRD_INT_STEERING_PCIE_APP— routed to the PCIe host.
Like the vector, steering is set per category. Both the vector and steering calls require the categoryType parameter, not the individual status type.
|
Important
|
Common Errors
|
ISR Mechanism
The sample supports two interrupt delivery modes, selected at compile time by the RUN_ISR preprocessor define.
ISR Mode (RUN_ISR Defined)
When RUN_ISR is defined, the application installs a hardware ISR after configuring interrupts for all channels:
check_status(naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE,
(nai_isr_t)MyIRIGIsr, NULL));
naibrd_InstallISR() registers the MyIRIGIsr callback to handle hardware interrupts from the board. The NAIBRD_IRQ_ID_DONT_CARE parameter lets the library select the appropriate IRQ line automatically.
The ISR itself is lightweight — it records the vector, determines which status type triggered the event, and signals the main loop:
void MyIRIGIsr(void* param, uint32_t vector)
{
irqIRIGCount++;
isrLock = 1;
receivedVector = vector;
switch (vector)
{
case IRIG_CHANNEL1_INTERRUPT_VECTOR:
receivedType = type[0];
interruptStatus = INTERRUPT_RECEIVED;
break;
default:
receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
receivedChannelStatus = 0;
interruptStatus = INTERRUPT_ERROR_UNEXPECTED_VECTOR;
break;
}
isrLock = 0;
}
The ISR uses the isrLock flag to prevent the main loop from reading shared variables while they are being updated. In ISR mode, the main loop reads the latched status register after the ISR signals an event:
check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, receivedType, &channelStatus));
receivedChannelStatus = channelStatus;
This deferred status read keeps the ISR fast — it only captures the vector and signals the event. The heavier register read happens in the main loop context.
Polling Mode (RUN_ISR Not Defined)
When RUN_ISR is not defined, no ISR is installed. Instead, the main loop calls CheckForStatusChange() on each iteration to poll the latched status register:
static void CheckForStatusChange(int32_t cardIndex, int32_t modNum,
int32_t channelCount)
{
nai_status_bit_t channelStatus;
static int32_t chanIndex = 0;
do
{
check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum,
FIRST_IRIG_CHANNEL_IDX + 1, type[chanIndex], &channelStatus));
if (NAI_STATUS_BIT_LO != channelStatus)
{
irqIRIGCount++;
receivedVector = vector[chanIndex];
receivedType = type[chanIndex];
receivedChannelStatus = channelStatus;
interruptStatus = INTERRUPT_RECEIVED;
}
chanIndex++;
} while ((chanIndex < channelCount) && (INTERRUPT_RECEIVED != interruptStatus));
if (chanIndex >= channelCount)
{
chanIndex = 0;
}
}
The function uses a static chanIndex to round-robin across channels. On each call, it checks one or more channels until it either finds an active status or exhausts the channel list. When multiple interrupts are pending simultaneously, successive calls will discover them one at a time.
Polling mode is useful for development and debugging because it does not require ISR installation or specific bus interrupt routing. However, it introduces latency proportional to the polling interval. For production systems that require prompt interrupt response, use ISR mode.
|
Important
|
Common Errors
|
Event Processing and Status Clearing
The main loop in Run_IRIG_Interrupts() continuously checks the interruptStatus flag and processes events as they arrive:
do
{
/* In polling mode, check status registers each iteration */
/* In ISR mode, the ISR sets interruptStatus asynchronously */
if (isrLock == 0)
{
switch (interruptStatus)
{
case INTERRUPT_RECEIVED:
printf("Interrupt Received: Vector- 0x%X, ChannelStatus- 0x%X, count- %u\n",
receivedVector, receivedChannelStatus, irqIRIGCount);
ClearInterrupt(cardIndex, modNum, receivedType);
break;
case INTERRUPT_ERROR_UNEXPECTED_VECTOR:
printf("Unexpected Interrupt Received: Vector- 0x%X, count- %u\n",
receivedVector, irqIRIGCount);
break;
case INTERRUPT_WAITING:
break;
}
}
} while (bContinue);
When an event is received, the loop prints the vector, channel status, and running count. It then calls ClearInterrupt() to clear the latched status and reset the application state so the next event can be captured.
Clearing Latched Status
Subsequent interrupts will not fire until the previous latched status has been cleared. The ClearInterrupt() function handles both the hardware and application-level reset:
static void ClearInterrupt(int32_t cardIndex, int32_t module,
naibrd_irig_event_mapped_status_type_t type)
{
check_status(naibrd_IRIG_ClearEventMappedStatus(cardIndex, module,
FIRST_IRIG_CHANNEL_IDX + 1, type));
receivedVector = 0xFFFFFFFF;
receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
receivedChannelStatus = NAI_STATUS_BIT_LO;
irqIRIGCount = 0;
interruptStatus = INTERRUPT_WAITING;
}
naibrd_IRIG_ClearEventMappedStatus() writes to the hardware status register to clear the latched condition. The function then resets all shared variables to their initial state. Note that the interrupt count (irqIRIGCount) is also reset to zero, so the count reflects interrupts since the last clear rather than a cumulative total.
In your own application, you must clear latched status after handling each interrupt. Failing to do so will prevent subsequent interrupts of the same type from firing. The sample also calls ClearInterrupt() during initialization (before Setup_IRIG_Interrupts()) to ensure no stale latched status from a previous run triggers an immediate spurious interrupt.
|
Important
|
Common Errors
|
Troubleshooting Reference
The following table summarizes errors and symptoms covered in preceding sections along with additional diagnostics. Consult your module’s manual for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Board not powered or not connected. Configuration file has wrong interface or address. |
Verify physical connection and power. Delete the configuration file and re-run to enter settings from scratch. |
Connection timeout |
Network misconfiguration, firewall blocking traffic, or incorrect bus settings. |
Confirm IP settings for Ethernet connections. Check PCI/PCIe bus enumeration for local connections. |
Module not present at selected slot |
The selected slot does not contain an RG1 module. |
Use the board menu to list populated slots and select the correct module number. |
No interrupts fire |
Interrupt steering does not match hardware bus. Interrupt enable not set. Status condition has not occurred. |
Verify steering matches your connection type (onboard, cPCI, PCIe). Confirm enable returned success. Remove the IRIG signal to trigger BIT data loss. |
Only one interrupt received |
Latched status not cleared after handling. |
Call |
Spurious interrupt on startup |
Stale latched status from a previous run. |
Clear all latched status before enabling interrupts. The sample calls |
Unexpected vector in ISR |
Another module is generating interrupts with a conflicting vector value. |
Assign unique vector values per module. Verify vector assignments across all modules on the board. |
|
Module does not support the specified status type, or firmware revision is too old. |
Verify module type is RG1. Check firmware revision against the module manual requirements. |
Polling mode detects nothing |
The monitored condition (BIT data loss) has not occurred on the hardware. |
Disconnect or remove the IRIG signal source to trigger the data loss condition. Verify the correct status type is configured. |
Full Source
Full Source — RG_Interrupts.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#if defined (__VXWORKS__)
#include "vxBusLib.h"
#endif
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_irig.h"
#include "advanced/nai_ether_adv.h"
#define TIMEOUT 1000 /* 1 second */
#define FIRST_IRIG_CHANNEL_IDX 0
#define IRIG_CHANNEL1_INTERRUPT_VECTOR 0x000000A1u
//#define IRIG_CHANNEL2_INTERRUPT_VECTOR 0x000000A2u
static const int8_t *CONFIG_FILE = (const int8_t *)"default_RGInterrupts.txt";
typedef enum interrupt_status_type_e
{
INTERRUPT_WAITING,
INTERRUPT_RECEIVED,
INTERRUPT_ERROR_UNEXPECTED_VECTOR
} interrupt_status_type_t;
/* Function prototypes */
void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid);
void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type,
uint32_t vector);
static void CheckForStatusChange(int32_t cardIndex, int32_t modNum, int32_t channelCount);
static void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type);
#if defined (__VXWORKS__)
void MyIRIGIsr(uint32_t nVector);
#else
void MyIRIGIsr(void* param, uint32_t vector);
#endif
const static naibrd_irig_event_mapped_status_type_t type[] = {
NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED
/* TODO: NAI_IRIG_STATUS_CHANNEL1_LATCHED, NAI_IRIG_STATUS_CHANNEL2_LATCHED, NAI_IRIG_STATUS_CHANNEL3_LATCHED,
NAI_IRIG_STATUS_CHANNEL4_LATCHED,
NAI_IRIG_STATUS_CHANNEL5_LATCHED, NAI_IRIG_STATUS_CHANNEL6_LATCHED, NAI_IRIG_STATUS_CHANNEL7_LATCHED,
NAI_IRIG_STATUS_CHANNEL8_LATCHED*/
};
const static uint32_t vector[] = {
IRIG_CHANNEL1_INTERRUPT_VECTOR
/* TODO: IRIG_CHANNEL1_INTERRUPT_VECTOR, IRIG_CHANNEL2_INTERRUPT_VECTOR, IRIG_CHANNEL3_INTERRUPT_VECTOR,
IRIG_CHANNEL4_INTERRUPT_VECTOR,
IRIG_CHANNEL5_INTERRUPT_VECTOR, IRIG_CHANNEL6_INTERRUPT_VECTOR, IRIG_CHANNEL7_INTERRUPT_VECTOR,
IRIG_CHANNEL8_INTERRUPT_VECTOR*/
};
volatile uint32_t irqIRIGCount = 0;
volatile static uint8_t isrLock = 0;
volatile static uint32_t receivedVector = 0;
volatile static nai_status_bit_t receivedChannelStatus = 0;
volatile static naibrd_irig_event_mapped_status_type_t receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
volatile static interrupt_status_type_t interruptStatus = INTERRUPT_WAITING;
/**************************************************************************************************************/
/** \defgroup IRIGInterrupts IRIG Interrupts
The purpose of the IRIG Interrupts sample application is to illustrate the methods to call in the naibrd
library to configure a given IRIG TODO status to interrupt on. Interrupts in this example are routed
to the cPCI backplane.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t RG_Interrupts(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_IRIG_Interrupts(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;
}
/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Configures an IRIG module to interrupt on the TODO status. The user can choose, via the USE_ISR
preprocessor directive to use interrupts or poll instead.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum (Input) Module Number of the module to access (1 - [max modules for board]).
\param modid (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
int32_t channelCount;
int32_t chanIndex;
bool_t bContinue = TRUE;
#if defined (RUN_ISR)
nai_status_bit_t channelStatus;
#endif
channelCount = naibrd_IRIG_GetChannelCount(modid);
for (chanIndex = FIRST_IRIG_CHANNEL_IDX; chanIndex < channelCount; chanIndex++)
{
/* Make sure there are no pending interrupts before they are enabled. */
ClearInterrupt(cardIndex, modNum, type[chanIndex]);
/* Setup Interrupts */
Setup_IRIG_Interrupts(cardIndex, modNum, type[chanIndex], vector[chanIndex]);
}
#if defined (RUN_ISR)
/* Install the ISR */
check_status(naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE, (nai_isr_t)MyIRIGIsr, NULL));
#endif
printf("\nInterrupts are fired from a NAI-75G5 to NAI-INT2. Modify the parameters in");
printf("\nthe function naibrd_InstallISR and naibrd_IRIG_SetEventMappedInterruptSteering for other interrupt configuration.");
printf("\nWaiting for Interrupts .....\n");
do
{
#if !defined (RUN_ISR)
CheckForStatusChange(cardIndex, modNum, channelCount);
#if defined (__VXWORKS__)
taskDelay(1);
#endif
#endif /* RUN_ISR */
if (isrLock == 0)
{
switch (interruptStatus)
{
case INTERRUPT_RECEIVED:
{
/* This indicates that we received the interrupt that was expected. */
#if defined (RUN_ISR)
/* Read the latched channel status register to see what caused the interrupt. */
check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, receivedType, &channelStatus));
receivedChannelStatus = channelStatus;
#endif /* RUN_ISR */
printf("Interrupt Received: Vector- 0x%X, ChannelStatus- 0x%X, count- %u\n",
receivedVector, receivedChannelStatus, irqIRIGCount);
/* Subsequent interrupts will not occur until the previous ones have been cleared. */
ClearInterrupt(cardIndex, modNum, receivedType);
break;
}
case INTERRUPT_ERROR_UNEXPECTED_VECTOR:
{
/* This indicates that we received the interrupt that was not expected. */
printf("Unexpected Interrupt Received: Vector- 0x%X, count- %u\n",
receivedVector, irqIRIGCount);
break;
}
case INTERRUPT_WAITING:
{
/* Nothing to do but wait for an interrupt. */
break;
}
default:
break;
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
} while (bContinue);
}
/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Configures an IRIG module to interrupt on the TODO status.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum (Input) Module Number of the module to access (1 - [max modules for board]).
\param type (Input) Interrupt Status Type: refer to naibrd_irig_event_mapped_status_type_t definition.
\param vector (Input) Interrupt vector to identify which channel caused the interrupt.
*/
/**************************************************************************************************************/
void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type,
uint32_t vector)
{
naibrd_irig_event_mapped_category_type_t categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
switch (type)
{
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_REALTIME:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
break;
case NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_REF_PULSE_RX_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_REF_PULSE_RX_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_INTERRUPT_1PPS_OUTPUT_HIGH_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_INTERRUPT_1PPS_OUTPUT_HIGH_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_RX_CONTROL_BITS_CHANGED_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_RX_CONTROL_BITS_CHANGED_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_CONTROL_BITS_RX_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_CONTROL_BITS_RX_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_CHANGE_REF_SRC_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_CHANGE_REF_SRC_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_USER_INTERRUPT_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_USER_INTERRUPT_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_DST_ADJUST_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_DST_ADJUST_REALTIME:
case NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_LATCHED:
case NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_REALTIME:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_GENERAL;
break;
default:
categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
break;
}
check_status(naibrd_IRIG_SetEventMappedInterruptTriggerType(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type, NAIBRD_IRIG_EDGE_INTERRUPT));
check_status(naibrd_IRIG_SetEventMappedInterruptVector(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, categoryType, vector));
check_status(naibrd_IRIG_SetEventMappedInterruptSteering(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, categoryType, NAIBRD_INT_STEERING_CPCI_APP));
check_status(naibrd_IRIG_SetEventMappedInterruptEnable(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type, TRUE));
}
#if defined (RUN_ISR)
/*****************************/
/* Interrupt Service Routine */
/*****************************/
#if defined (__VXWORKS__)
void MyIRIGIsr(uint32_t nVector)
#else
void MyIRIGIsr(void* param, uint32_t vector)
#endif
{
irqIRIGCount++;
isrLock = 1;
#if defined (WIN32)
UNREFERENCED_PARAMETER(param);
#endif
#if defined (__VXWORKS__)
/* Get the vector that caused the interrupt */
unsigned int vector = nai_Onboard_GetInterruptVector();
/* Clear Interrupt */
nai_Onboard_ClearInterrupt();
#endif
/* Determine what interrupt was received */
receivedVector = vector;
switch (vector)
{
case IRIG_CHANNEL1_INTERRUPT_VECTOR:
receivedType = type[0];
interruptStatus = INTERRUPT_RECEIVED;
break;
case IRIG_CHANNEL2_INTERRUPT_VECTOR:
interruptStatus = INTERRUPT_RECEIVED;
receivedType = type[1];
break;
default:
receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
receivedChannelStatus = 0;
interruptStatus = INTERRUPT_ERROR_UNEXPECTED_VECTOR;
break;
}
isrLock = 0;
}
#else
/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Checks each channel (up to channelCount) for the TODO status. Set's interrupt received flag
if condition has been met. This is function is only called if the user undefined RUN_ISR.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum (Input) Module Number of the module to access (1 - [max modules for board]).
\param channelCount (Input) Channel Number of the channel to access (1 - [max channels for module]).
*/
/**************************************************************************************************************/
static void CheckForStatusChange(int32_t cardIndex, int32_t modNum, int32_t channelCount)
{
nai_status_bit_t channelStatus;
static int32_t chanIndex = 0;
/* chanIndex is a static variable and allows processing multiple interrupts. In the event that multiple
interrupts occur at once, the first interrupt is flagged and every subsequent call to this function will
check the next channel and flag the interrupt. */
do
{
check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type[chanIndex], &channelStatus));
if (NAI_STATUS_BIT_LO != channelStatus)
{
irqIRIGCount++;
receivedVector = vector[chanIndex];
receivedType = type[chanIndex];
receivedChannelStatus = channelStatus;
interruptStatus = INTERRUPT_RECEIVED;
}
chanIndex++;
} while ((chanIndex < channelCount) && (INTERRUPT_RECEIVED != interruptStatus));
if (chanIndex >= channelCount)
{
chanIndex = 0;
}
}
#endif /* RUN_ISR */
/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Clears channel status and resets applicable application variables to allow another interrupt to occur.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum (Input) Module Number of the module to access (1 - [max modules for board]).
\param type (Input) Interrupt Status Type: refer to naibrd_irig_event_mapped_status_type_t definition.
*/
/**************************************************************************************************************/
static void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type)
{
check_status(naibrd_IRIG_ClearEventMappedStatus(cardIndex, module, FIRST_IRIG_CHANNEL_IDX + 1, type));
receivedVector = 0xFFFFFFFF;
receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
receivedChannelStatus = NAI_STATUS_BIT_LO;
irqIRIGCount = 0;
interruptStatus = INTERRUPT_WAITING;
}