Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

TTL Interrupt

TTL Interrupt Sample Application (SSK 1.x)

Overview

The TTL Interrupt sample application demonstrates how to configure and handle hardware interrupts on TTL (Transistor-Transistor Logic) digital I/O modules using the NAI Software Support Kit (SSK 1.x). The sample covers two interrupt delivery mechanisms: standard (onboard ISR with a message queue and thread-based processing) and Ethernet IDR (Interrupt Driven Response, network-based). Both variants configure Lo-Hi transition, Hi-Lo transition, and BIT latched status interrupts on a user-selected range of channels and share the same module-level configuration code in nai_ttl_int.c. The difference is only in how the interrupt notification reaches your application.

This sample supports the following TTL module types: D7, TL1, TL2, TL3, TL4, TL5, TL6, TL7, and TL8.

The sample ships as two separate executables:

  • TTL_Interrupt — standard interrupt delivery. Installs a hardware ISR (onboard or offboard), enables Lo-Hi transition, Hi-Lo transition, and BIT latched status interrupts on a user-selected channel range, and processes interrupt events through a message queue and handler thread. Unlike TTL_Interrupt_Basic, this variant handles multiple simultaneous interrupts across a range of channels, supports both onboard and offboard ISR routing, and monitors all three latched status types with distinct interrupt vectors.

  • TTL_Interrupt_Ethernet — Ethernet IDR variant. Delivers interrupt notifications over the network using IDR commands. The board automatically reads the Lo-Hi and Hi-Lo transition latched status registers and sends the results to your application as UDP messages.

TTL modules expose the following latched interrupt status types:

  • BIT (NAI_TTL_STATUS_BIT_LATCHED) — Built-In Test fault detected on a TTL channel.

  • Overcurrent (NAI_TTL_STATUS_OVERCURRENT_LATCHED) — the channel output driver has exceeded its current limit.

  • Lo-Hi transition (NAI_TTL_STATUS_LO_HI_TRANS_LATCHED) — the channel input has transitioned from a logic-low to a logic-high state.

  • Hi-Lo transition (NAI_TTL_STATUS_HI_LO_TRANS_LATCHED) — the channel input has transitioned from a logic-high to a logic-low state.

This sample configures interrupts on the Lo-Hi transition, Hi-Lo transition, and BIT status types. To monitor the overcurrent status type, use the same configuration pattern shown here with the NAI_TTL_STATUS_OVERCURRENT_LATCHED constant. For basic TTL channel configuration and I/O operations, see the TTL BasicOps sample application guide. For a simpler single-channel interrupt example, see the TTL Interrupt Basic guide. For background on interrupt concepts — including edge vs. level triggering, interrupt vector numbering, steering architecture, and latency measurement — see the Interrupts API Guide.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a TTL module installed (D7, or TL1 through TL8).

  • 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.

  • For the Ethernet IDR variant: a Gen4 or later board with an Ethernet connection.

How to Run

Launch either executable from your build output directory. On startup the application looks for a configuration file (default_TTL_Interrupt.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 standard variant prompts you for channel range, trigger mode, and interrupt delivery options, then begins monitoring for interrupt events. The Ethernet variant prompts for a single channel number and IDR configuration parameters.

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 TTL. For details on board connection configuration, see the First Time Setup Guide.

Both variants follow the standard SSK 1.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file or present the interactive board menu. The configuration file 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.

  2. Initialize module and interrupt configuration structures with initializeTTLConfigurations() and initializeInterruptConfigurations().

  3. Query the user for card index with naiapp_query_CardIndex().

  4. Query the user for module number with naiapp_query_ModuleNumber().

  5. Retrieve the module ID with naibrd_GetModuleID() to verify a TTL module is installed at the selected slot.

initializeTTLConfigurations(0, 0, 0, 0, 0, 0);
initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, 0, 0, 0);

if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
   while (stop != TRUE)
   {
      stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
      inputTTLConfig.cardIndex = cardIndex;
      if (stop != TRUE)
      {
         check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
         stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
         inputTTLConfig.module = module;
         if (stop != TRUE)
         {
            inputTTLConfig.modid = naibrd_GetModuleID(cardIndex, module);
            if ((inputTTLConfig.modid != 0))
            {
               Run_TTL_Interrupt();
            }
         }
      }
   }
}

The TtlConfig structure tracks the board and module context throughout the application:

typedef struct
{
   int32_t cardIndex;
   int32_t module;
   uint32_t modid;
   int32_t channel;
   int32_t maxChannel;
   int32_t minChannel;
} TtlConfig;

In your own application, you will track the same values — card index, module slot number, module ID, and the channel range you intend to monitor.

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 or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain a TTL module. Use the board menu to verify which slots are populated.

User Configuration Queries

Before configuring interrupts, the standard variant (TTL_Interrupt) queries the user for several configuration parameters. These queries are a sample convenience — in your own application, you would set these values directly.

Channel Range

The sample prompts for a minimum and maximum channel number. All channels in this range will have interrupts enabled:

maxChannel = naibrd_TTL_GetChannelCount(inputTTLConfig.modid);
bQuit = naiapp_query_ForChannelRange(&inputTTLConfig.minChannel,
                                     &inputTTLConfig.maxChannel,
                                     minChannel, maxChannel);

naibrd_TTL_GetChannelCount() returns the total number of channels available on the module. The channel range determines which channels will have Lo-Hi, Hi-Lo, and BIT latched status interrupts enabled. Consult your module’s manual for the channel count on your specific module type.

Trigger Mode (Edge vs. Level)

bQuit = GetTTLLatchStatusTriggerMode(&inputInterruptConfig.interrupt_Edge_Trigger);

The GetTTLLatchStatusTriggerMode() function prompts for edge-triggered (0) or level-triggered (1) operation:

  • Edge-triggered (0) — the interrupt fires once when the status bit transitions from 0 to 1. This produces a single notification per event and is the default.

  • Level-triggered (1) — the interrupt continues to assert as long as the status condition remains active. This ensures your application does not miss events, but the interrupt will keep firing until you clear the status register.

Interrupt Clear Prompting

bQuit = QueryUserForClearingInterruptPrompts(&inputInterruptConfig.bPromptForInterruptClear);

When enabled, the handler pauses after each interrupt and waits for the user to press "C" before clearing the status register. This is useful for debugging — it lets you observe the interrupt state before re-arming. In a production application, you would clear the status automatically.

Onboard vs. Offboard ISR

bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);

This selects whether the ISR runs on the board’s onboard processor or on an external host connected via cPCI/PCIe. Onboard processing is the typical configuration for Ethernet-connected boards. Offboard processing is used when the board is installed in a CompactPCI or PCIe chassis and the host processor handles interrupts directly.

Interrupt Steering

bQuit = GetIntSteeringTypeFromUser(&inputInterruptConfig.steering);

Interrupt steering determines the physical path by which the interrupt signal reaches your handler:

  • Onboard (NAIBRD_INT_STEERING_ON_BOARD_0 or ON_BOARD_1) — handled locally on the board’s processor.

  • cPCI offboard (NAIBRD_INT_STEERING_CPCI_APP) — routes the interrupt to the CompactPCI backplane host.

  • PCIe offboard (NAIBRD_INT_STEERING_PCIE_APP) — routes the interrupt to the PCIe host.

Clearing Status and Configuring Interrupts

Before enabling interrupts, the configureTTLToInterrupt() function in nai_ttl_int.c clears stale latched status, assigns interrupt vectors for each status type, sets the trigger mode per-channel, and configures steering. Always clear status registers before enabling interrupts — stale latched status from a previous run or power-on state will trigger immediate spurious interrupts.

Disabling Existing Interrupts and Clearing Stale Status

The configuration function first disables any previously enabled interrupts and clears stale status for all three monitored status types:

enableTTLInterrupts(inputTTLConfig, FALSE);

check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, rawstatus));

check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, rawstatus));

check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_BIT_LATCHED, &rawstatus));
check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1,
             NAI_TTL_STATUS_BIT_LATCHED, rawstatus));

The pattern is read-then-clear: naibrd_TTL_GetGroupStatusRaw() reads the current latched status bitmask for a status type, then naibrd_TTL_ClearGroupStatusRaw() writes back the same value to clear those bits. The group number 1 indicates group 1, which covers all channels on the module. This is repeated for each of the three status types.

Interrupt Vectors

Each status type is assigned a distinct interrupt vector so the handler can identify which condition triggered the event:

check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1,
             NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, NAI_TTL_LOHI_INTERRUPT_VECTOR));
check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1,
             NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, NAI_TTL_HILO_INTERRUPT_VECTOR));
check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1,
             NAI_TTL_STATUS_BIT_LATCHED, NAI_TTL_BIT_INTERRUPT_VECTOR));

naibrd_TTL_SetGroupInterruptVector() sets the vector for all channels sharing a status type within the group. The predefined constants (NAI_TTL_LOHI_INTERRUPT_VECTOR, NAI_TTL_HILO_INTERRUPT_VECTOR, NAI_TTL_BIT_INTERRUPT_VECTOR) give each status type a unique vector. In your own application, choose vector values that do not conflict with other modules on the same board.

Trigger Mode Per-Channel

The trigger mode is set per-channel for each status type across all channels on the module:

for (chan = 1; chan <= inputTTLConfig.maxChannel; chan++)
{
   check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan,
                NAI_TTL_STATUS_LO_HI_TRANS_LATCHED,
                (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
   check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan,
                NAI_TTL_STATUS_HI_LO_TRANS_LATCHED,
                (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
   check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan,
                NAI_TTL_STATUS_BIT_LATCHED,
                (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
}

naibrd_TTL_SetEdgeLevelInterrupt() sets the trigger mode per-channel and per-status-type. The interrupt_Edge_Trigger value is 0 for edge-triggered or 1 for level-triggered, as selected by the user.

Interrupt Steering

check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1,
             NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, steering));
check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1,
             NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, steering));
check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1,
             NAI_TTL_STATUS_BIT_LATCHED, steering));

Steering is set per-status-type at the group level and applies to all channels. The steering value must match the interrupt delivery mechanism you are using: NAIBRD_INT_STEERING_ON_BOARD_0 for the standard onboard ISR, NAIBRD_INT_STEERING_ON_BOARD_1 for Ethernet IDR, or NAIBRD_INT_STEERING_CPCI_APP / NAIBRD_INT_STEERING_PCIE_APP for offboard delivery.

Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — the selected module does not support the specified status type or interrupt configuration. Verify the module type and consult the module manual.

  • Interrupts fire immediately after enable — stale latched status was not cleared before enabling. Always clear status registers before calling naibrd_TTL_SetInterruptEnable().

  • Wrong steering mode — if using the Ethernet IDR variant, steering must be set to NAIBRD_INT_STEERING_ON_BOARD_1, not ON_BOARD_0. Using ON_BOARD_0 with the Ethernet variant will deliver interrupts to the onboard ISR instead of generating IDR messages.

ISR Installation and Interrupt Handling (Standard Variant)

The standard variant installs a hardware ISR, initializes a message queue and processing thread, and then enables interrupts. This approach handles multiple simultaneous interrupts across a range of channels and distinguishes between Lo-Hi, Hi-Lo, and BIT events using distinct interrupt vectors.

Installing the ISR

The ISR is installed based on whether the user selected onboard or offboard processing:

setIRQ(inputInterruptConfig.steering, &inputInterruptConfig.irq);
inputInterruptConfig.cardIndex = inputTTLConfig.cardIndex;

if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
   check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex,
                inputInterruptConfig.irq, (nai_isr_t)IntOnboardIsr, NULL));
}
else
{
   check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex,
                inputInterruptConfig.irq, (nai_isr_t)IntOffboardIsr,
                (void*)&inputTTLConfig.cardIndex));
}

setIRQ() maps the steering value to the appropriate IRQ number. naibrd_InstallISR() registers the ISR callback with the board driver. The IntOnboardIsr and IntOffboardIsr functions are shared SSK utilities that post the interrupt vector to a message queue for asynchronous processing.

In your own application, call naibrd_InstallISR() with your own ISR callback. The ISR should be minimal — set a flag, post to a queue, or signal an event. Do not call blocking functions or perform lengthy operations inside the ISR.

Message Queue and Handler Thread

After installing the ISR and configuring the module, the sample initializes a message queue and a processing thread:

configureTTLToInterrupt(inputInterruptConfig, inputTTLConfig);

InitInterruptAppThread(ONBOARD_INT, 0);
nai_msDelay(10);
UpdateThreadState(RUN);

InitInterruptAppThread() creates a background thread that waits on the message queue for interrupt events. When the ISR fires, it posts the interrupt vector to the queue. The thread dequeues the vector and calls the registered handler function. The nai_msDelay(10) ensures the thread is fully initialized before the state is set to RUN.

Enabling Interrupts

With the ISR installed and the handler thread running, interrupts are enabled on all channels in the selected range for all three status types:

void enableTTLInterrupts(TtlConfig inputTTLConfig, bool_t enable) {
   int32_t channel;
   for (channel = inputTTLConfig.minChannel;
        channel <= inputTTLConfig.maxChannel; channel++)
   {
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex,
                   inputTTLConfig.module, channel,
                   NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, enable));
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex,
                   inputTTLConfig.module, channel,
                   NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, enable));
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex,
                   inputTTLConfig.module, channel,
                   NAI_TTL_STATUS_BIT_LATCHED, enable));
   }
}

naibrd_TTL_SetInterruptEnable() enables or disables interrupts per-channel and per-status-type. The function iterates through every channel in the selected range and enables all three status types on each channel.

Handling Interrupts

The handler function assigned to ttlIntProcessFunc is called by the background thread when an interrupt event arrives:

ttlIntProcessFunc = handleTTLInterrupt;

The handleTTLInterrupt() function uses the interrupt vector to determine which status type triggered the event, reads and clears the corresponding latched status, and displays the results:

void handleTTLInterrupt(uint32_t nVector) {
   uint32_t rawstatus = 0;

   printf("\n\nInterrupt Occurred \n\n");
   if (inputInterruptConfig.bPromptForInterruptClear)
   {
      promptUserToClearInterrupt_TTL();
   }

   switch (nVector)
   {
      case NAI_TTL_LOHI_INTERRUPT_VECTOR:
         printf("LoHi Transition Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, rawstatus));
         break;
      case NAI_TTL_HILO_INTERRUPT_VECTOR:
         printf("HiLo Transition Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, rawstatus));
         break;
      case NAI_TTL_BIT_INTERRUPT_VECTOR:
         printf("BIT Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_BIT_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex,
                      inputTTLConfig.module, 1,
                      NAI_TTL_STATUS_BIT_LATCHED, rawstatus));
         break;
   }
   printInterruptInformation_TTL(nVector, rawstatus, FALSE);
}

The handler pattern is: optionally pause for user acknowledgment (debugging feature), identify which status type triggered based on the vector, read the raw group status to identify which channels triggered, clear the status to re-arm the interrupt, and display the results. The printInterruptInformation_TTL() function prints the interrupt vector and status bitmask.

In the status bitmask, each bit corresponds to a channel. For example, if rawstatus is 0x05, channels 1 and 3 (bits 0 and 2) have the corresponding transition condition active. When the isEther parameter is FALSE, the print function labels the interrupt identifier as "Vector."

Cleanup

When the user exits, the application disables interrupts and uninstalls the ISR:

enableTTLInterrupts(inputTTLConfig, FALSE);
check_status(naibrd_UninstallISR(inputInterruptConfig.cardIndex));

Always disable interrupts before uninstalling the ISR. If you uninstall the ISR while interrupts are still enabled, the board may attempt to deliver interrupts to a handler that no longer exists.

Important

Common Errors

  • ISR never fires — verify that steering is set correctly for your interrupt delivery mechanism and that naibrd_InstallISR() succeeded. Check that the IRQ number matches the steering configuration.

  • Handler not called despite ISR firing — the message queue or handler thread may not be initialized. Ensure InitInterruptAppThread() is called before enabling interrupts and that UpdateThreadState(RUN) activates the thread.

  • Continuous interrupts without new transition events — with level-triggered mode, the interrupt re-asserts immediately if status is not cleared. Ensure the handler calls naibrd_TTL_ClearGroupStatusRaw() to re-arm the interrupt.

  • Thread never terminates — the background thread runs until the user presses "Q". Ensure the application checks isThreadStateTerminated() and cleanly exits the wait loop.

  • Wrong vector in handler — if the handler always falls through the switch without matching a vector, verify that the vectors assigned in configureTTLToInterrupt() match the constants used in the handler (NAI_TTL_LOHI_INTERRUPT_VECTOR, NAI_TTL_HILO_INTERRUPT_VECTOR, NAI_TTL_BIT_INTERRUPT_VECTOR).

Ethernet IDR Interrupt Handling

The Ethernet IDR variant (TTL_Interrupt_Ethernet) delivers interrupt notifications over the network instead of through a local ISR. Use this approach when your application runs on a remote host connected via Ethernet, when a hardware ISR is not available or practical for your deployment, or when you want the board to automatically read status registers and package the results into UDP messages.

How the Ethernet IDR Mechanism Works

The Ethernet IDR mechanism works as follows:

  1. Your application configures IDR definitions on the board — one for Lo-Hi transitions and one for Hi-Lo transitions. Each specifies: a trigger vector, a response IP address and port, a transport protocol (UDP), and a set of Ethernet commands (register reads) to execute when the interrupt fires.

  2. When the specified interrupt vector fires on the board, the board’s onboard processor automatically executes the pre-configured Ethernet commands — reading the Lo-Hi and Hi-Lo transition latched status registers.

  3. The board packages the results into Ethernet messages and sends them to the configured IP address and port.

  4. Your application runs a listener (IDR server) that receives and decodes these messages.

This approach eliminates the need for your host application to poll registers over the network. The board does the register reads locally (fast) and sends only the results over the network, reducing round-trips and latency.

Prerequisites

Ethernet IDR requires a Generation 4 or later board with Ethernet support. The Ethernet variant verifies this at startup:

bGen4ttlIDRCommands = SupportsGen4Ether(inputTTLConfig.cardIndex);
if (!bGen4ttlIDRCommands)
{
   printf("TTL Ethernet Interrupt Support Prior to Generation 4 "
          "Ethernet commands currently not supported\n");
   bQuit = TRUE;
}

If the check fails, the board’s firmware does not support the Gen4 Ethernet protocol and IDR commands will not work. You may need to update the board firmware.

IDR Configuration

The Ethernet variant prompts the user for the IDR response IP address and port (defaults: 192.168.1.100:52802), then builds and registers two IDR definitions — one for Lo-Hi transitions (DEF_ETHERNET_TTL_LOHI_IDR_ID) and one for Hi-Lo transitions (DEF_ETHERNET_TTL_HILO_IDR_ID). Two IDR definitions are needed because each monitors a different status type with a different interrupt vector.

The setupIDRConfiguration_TTL() function constructs Ethernet commands and registers both IDR definitions:

check_status(naibrd_Ether_ClearIDRConfig(cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
InitTTLIDRCommands(inputTTLConfig, inputIDRConfig,
                   bGen4TTLIDRCommands, addr);
check_status(naibrd_Ether_SetIDRConfig(cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID,
             protocol, ipLength, ipAddress, port, vector1,
             *cmdcount, *cmdlength, commands));

check_status(naibrd_Ether_ClearIDRConfig(cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));
check_status(naibrd_Ether_SetIDRConfig(cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID,
             protocol, ipLength, ipAddress, port, vector2,
             *cmdcount, *cmdlength, commands));

The InitTTLIDRCommands() function constructs the Ethernet read command by resolving the board address and module offset:

status = check_status(naibrd_GetModuleOffset(inputTTLConfig.cardIndex,
         inputTTLConfig.module, &moduleOffset));
if (status == NAI_SUCCESS)
   status = check_status(naibrd_GetAddress(inputTTLConfig.cardIndex,
            &boardAddress));

These addresses are combined with the Lo-Hi transition latched status register offset (NAI_TTL_GEN5_REG_LO_HI_TRANS_LATCHED_STATUS_ADD) to form the full register address for the Ethernet read command. The read command is configured with a stride of 16 and a count of TTL_INTERRUPT_RESPONSE_REG_COUNT (2), which reads both the Lo-Hi and Hi-Lo transition latched status registers in a single command.

After registration, both IDRs are started:

check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));

Onboard vs. Offboard IDR

The Ethernet variant supports both onboard and offboard IDR processing. This determines the board interface and steering used for the IDR commands:

if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
   inputIDRConfig.cardIndex = inputTTLConfig.cardIndex;
   inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
   inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else
{
   inputIDRConfig.cardIndex = 0;
   inputIDRConfig.boardInterface = NAI_INTF_PCI;
   inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
}

For onboard processing, steering is set to ON_BOARD_1 (which triggers the IDR mechanism). For offboard processing, the board interface is set to PCI and steering routes to the cPCI host.

Decoding IDR Responses

When the IDR server receives a message, it calls HandleTTLEtherInterrupt() to decode and process the results:

void HandleTTLEtherInterrupt(uint16_t msglen, uint8_t msg[],
                             uint16_t tdr_idr_id)
{
   uint16_t seq;
   nai_ether_typecode_t tc;
   nai_ether_gen_t gen = NAI_ETHER_GEN4;
   int32_t size;
   int32_t offset;
   uint16_t datacnt = 0;
   uint32_t data;
   uint32_t ttlstatus_int[TTL_INTERRUPT_RESPONSE_REG_COUNT];
   nai_ttl_status_type_t ttl_status_type = NAI_TTL_STATUS_BIT_LATCHED;

   offset = nai_ether_DecodeMessageHeader(msg, msglen, &seq, &tc, gen, &size);

   switch (tc)
   {
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
         datacnt = (msglen - 10) / NAI_REG32;
         for (i = 0; i < datacnt; i++)
         {
            data = 0;
            data = msg[offset++] << 24;
            data |= msg[offset++] << 16;
            data |= msg[offset++] << 8;
            data |= msg[offset++];
            if (i < TTL_INTERRUPT_RESPONSE_REG_COUNT)
               ttlstatus_int[i] = data;
         }
         break;
   }

   if (datacnt == TTL_INTERRUPT_RESPONSE_REG_COUNT)
   {
      for (i = 0; i < TTL_INTERRUPT_RESPONSE_REG_COUNT; i++)
      {
         if (ttlstatus_int[i] != 0)
         {
            /* Print and clear the status */
            check_status(naibrd_TTL_ClearGroupStatusRaw(
                         inputTTLConfig.cardIndex,
                         inputTTLConfig.module, 1,
                         ttl_status_type, ttlstatus_int[i]));
         }
      }
   }
}

The handler decodes the Gen4 Ethernet response header, extracts the Lo-Hi and Hi-Lo transition latched status register values from the read response data, and clears each non-zero status to re-arm the interrupt. The tdr_idr_id identifies which IDR definition triggered the response. The two data elements correspond to: index 0 = Lo-Hi transition status, index 1 = Hi-Lo transition status. When isEther is TRUE, the printInterruptInformation_TTL() function labels the interrupt identifier as "IDR ID" rather than "Vector."

Stopping the IDR

When the user exits, both IDRs must be stopped and cleaned up:

check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));
check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex,
             (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));

Always stop the IDR before closing the connection. If you close the connection without stopping the IDR, the board will continue sending messages to an address that is no longer listening.

Important

Common Ethernet IDR Errors

  • "Generation 4 Ethernet commands currently not supported" — the board firmware is older than Generation 4 and does not support IDR commands. Update the board firmware to Gen4 or later to use Ethernet IDR.

  • No IDR messages received — verify that the response IP address and port configured in the IDR match the address your application is listening on. Check that no firewall is blocking inbound UDP traffic on port 52802, and confirm that naibrd_Ether_StartIDR() was called after naibrd_Ether_SetIDRConfig().

  • Message parsing errors — if the typecode is not NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4, the board may have returned an error response. Verify that the protocol generation matches (NAI_ETHER_GEN4) and that the IDR commands were constructed with the correct register addresses.

  • Status always zero in IDR response — the register address may be incorrect. Verify that naibrd_GetModuleOffset() succeeded and that the module offset is correct for your board configuration.

  • Socket bind failure — the configured response port (52802) is already in use by another application or a previous instance that did not shut down cleanly. Change the port or terminate the conflicting process.

Troubleshooting Reference

This table summarizes common errors and symptoms covered in the sections above. For detailed context, refer to the relevant section. Consult your module’s manual for hardware-specific diagnostic procedures.

Debugging Interrupts That Are Not Firing

When interrupts are not being delivered, use this two-step approach to isolate the problem:

  1. Check whether the status registers are changing. Call naibrd_TTL_GetGroupStatusRaw() with NAI_TTL_STATUS_LO_HI_TRANS_LATCHED or NAI_TTL_STATUS_HI_LO_TRANS_LATCHED to read the latched status. If the status bits are changing when you toggle the TTL input, the module is detecting events correctly — the issue is in your interrupt delivery path (steering, ISR installation, or IDR configuration).

  2. If the status registers are NOT changing, the issue is at the hardware or channel configuration level. Verify that the TTL module is installed correctly, that signals are connected to the correct input pins, and that the channels are functional. Consult your module’s manual for TTL signal levels and 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 the configuration file exists, check that it lists the correct interface and address. If it does not exist, the board menu will appear — configure and save your connection settings.

Module not detected or channel count is 0

No TTL module installed at the selected slot, incorrect module number, or a non-TTL module is present

Verify hardware configuration. naibrd_TTL_GetChannelCount() returning 0 indicates the selected module is not a TTL type.

Spurious interrupts immediately after enable

Stale latched status from previous run or power-on state

Always clear all status registers before enabling interrupts. Use the clear-then-configure pattern shown in configureTTLToInterrupt().

No transition interrupts

No signal transition present on the TTL input, wrong steering mode, ISR not installed

Verify that a signal transition is actually occurring on the TTL channels (toggle the input between logic-low and logic-high). Confirm steering matches your delivery mechanism.

ISR never fires

Wrong IRQ, steering mismatch, naibrd_InstallISR() failed

Verify that setIRQ() mapped the correct IRQ for your steering value and that naibrd_InstallISR() returned success.

Handler thread not processing interrupts

Message queue not initialized, thread not in RUN state

Ensure InitInterruptAppThread() is called before enabling interrupts and UpdateThreadState(RUN) activates the thread.

Continuous interrupts without new transition events

Level-triggered mode active and status not cleared

Verify the handler calls naibrd_TTL_ClearGroupStatusRaw() after processing each interrupt. Consider switching to edge-triggered mode.

Only Lo-Hi or Hi-Lo interrupts received, not both

Only one transition direction is occurring on the input signal

Verify that the input signal completes a full cycle (low-to-high and high-to-low). Both transition types have separate vectors and status registers.

Ethernet IDR: no messages received

Wrong response IP/port, firewall blocking, IDR not started, Gen4 not supported

Verify IP address and port match your listener. Confirm naibrd_Ether_StartIDR() was called for both Lo-Hi and Hi-Lo IDR IDs. Check firewall rules for the configured port.

Steering mismatch

Steering set to wrong destination for the chosen delivery mechanism

Match steering to where your application executes. Standard onboard ISR: ON_BOARD_0. Ethernet IDR: ON_BOARD_1. External PCI: CPCI_APP. External PCIe: PCIE_APP.

Full Source

The complete source for this sample is provided below for reference. The sections above explain each part in detail. This sample consists of two main application files and three shared utility files.

Full Source — TTL_Interrupt.c (SSK 1.x)
/**************************************************************************************************************/
/**
<summary>

The TTL_Interrupt program demonstrates how to perform an interrupt when a single channel receives
a message. The purpose of this program is to demonstrate the method calls in the naibrd library for performing
the interrupt. More information on this process can be found in the naibrd SSK Quick Guide(Interrupts) file.

This application differs from TTL_Interrupt_Basic in that it could handle multiple interrupts at once.
It also queries the user for the edge trigger value and whether the user should be prompted to clear an interrupt.
The application also has support for offboard interrupts.

</summary>
*/
/**************************************************************************************************************/

/************************/
/* Include Declarations */
/************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/*Common Module Specific Sample Program include files*/
#include "nai_ttl_int.h"
#include "nai_ttl_cfg.h"
#include "nai_ttl_int_ether.h"

/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#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"

/* Module Specific NAI Board Library files */
#include "functions/naibrd_ttl.h"

InterruptConfig inputInterruptConfig;
IntProcessFuncDef ttlIntProcessFunc;

/* Extern Functions or Variables*/
extern TtlConfig inputTTLConfig;

/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/

/*
static const int8_t *App_Name = "TTL Interrupt";
static const int8_t *App_Rev = "1.0";
*/

static const int8_t *CONFIG_FILE = (int8_t *)"default_TTL_Interrupt.txt";

/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_TTL_Interrupt();

/**************************************************************************************************************/
/*****                                     Main Routine                                                   *****/
/**************************************************************************************************************/
/**************************************************************************************************************/
/**
<summary>

The main routine assists in gaining access to the board.

The following routines from the nai_sys_cfg.c file are
called to assist with accessing and configuring the board.

 - ConfigDevice
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - CheckModule

</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t TTL_Interrupt(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   initializeTTLConfigurations(0, 0, 0, 0, 0, 0);
   initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, 0, 0, 0);

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         inputTTLConfig.cardIndex = cardIndex;
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            inputTTLConfig.module = module;
            if (stop != TRUE)
            {
               inputTTLConfig.modid = naibrd_GetModuleID(cardIndex, module);
               if ((inputTTLConfig.modid != 0))
               {
                  Run_TTL_Interrupt();
               }
            }
         }
         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}
/**************************************************************************************************************/
/**
<summary>

This function is broken into the following major steps. These steps correspond with the steps provided
in the naibrd SSK Quick Guide(Interrupts) file.

2. Bus Interrupt Handling - Install ISR

   API CALLS - naibrd_InstallISR

3. Enable Module Interrupts- Configures module to interrupt when channel receives TTL message.

   API CALLS - naibrd_TTL_SetInterruptEdgeLevel, naibrd_TTL_SetIntVector, naibrd_TTL_SetInterruptSteering, naibrd_TTL_SetIntEnable

4. Not applicable for TTL module

5. Show Interrupt Handling - Check the mailbox to see if any interrupts occurred.

6. Re-arming Interrupts - Clear the status register to allow interrupts to occur again. This is done by writing to the status register.
   In this program, we use an API call to do this.

   API CALLS - naibrd_TTL_ClearStatus

7. Clear Module Configurations

8. Clear Board Configurations

   API CALLS - naibrd_UninstallISR

</summary>
*/
/**************************************************************************************************************/
static bool_t Run_TTL_Interrupt()
{

    bool_t bQuit = FALSE;

   int32_t minChannel;
   int32_t maxChannel;

   minChannel = 1;
   maxChannel = naibrd_TTL_GetChannelCount(inputTTLConfig.modid);

   /*Query for Channels to Operate on*/
   bQuit = naiapp_query_ForChannelRange(&inputTTLConfig.minChannel,&inputTTLConfig.maxChannel,minChannel,maxChannel);
   /*Query for Trigger Status of interrupts*/
   if(!bQuit)
   {
      bQuit = GetTTLLatchStatusTriggerMode(&inputInterruptConfig.interrupt_Edge_Trigger);
   }
   /*Query user if they'd like to be prompted for clearing interrupts*/
   if(!bQuit)
   {
      bQuit = QueryUserForClearingInterruptPrompts(&inputInterruptConfig.bPromptForInterruptClear);
   }
   if(!bQuit)
   {
      bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
   }
   /*Query user for location interrupt will be sent out to*/
   if(!bQuit)
   {
      bQuit = GetIntSteeringTypeFromUser(&inputInterruptConfig.steering);
   }
   if (!bQuit)
   {
      /**** 2. Implement Bus Interrupt Handling****/
      setIRQ(inputInterruptConfig.steering,&inputInterruptConfig.irq);
      inputInterruptConfig.cardIndex = inputTTLConfig.cardIndex;

      if(inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
      {
         check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex,inputInterruptConfig.irq,(nai_isr_t)IntOnboardIsr,NULL));
      }
      else
      {
         check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex,inputInterruptConfig.irq,(nai_isr_t)IntOffboardIsr, (void*)&inputTTLConfig.cardIndex));
      }
      /****3. configure Module to perform interrupts****/
      configureTTLToInterrupt(inputInterruptConfig,inputTTLConfig);

      /****Initialize Message Queue ****/
      InitInterruptAppThread(ONBOARD_INT, 0);
      nai_msDelay(10);
      UpdateThreadState(RUN);

      /****Enable Interrupts****/
      enableTTLInterrupts(inputTTLConfig,TRUE);

      /***5. Show Interrupt Handling (contains step 6) ***/
      ttlIntProcessFunc  = handleTTLInterrupt;

      /***Request user triggers interrupt ***/
      DisplayMessage_TTLInterrupt(MSG_USER_TRIGGER_TTL_INT);

      /****Wait on program threads****/
      while (!isThreadStateTerminated()){}
      bQuit = TRUE;

      /*****7. Clear Module Configurations*****/
      enableTTLInterrupts(inputTTLConfig,FALSE);

      /*****8. Clear Board Configurations *****/
      check_status(naibrd_UninstallISR(inputInterruptConfig.cardIndex));
   }
   return bQuit;
}
Full Source — TTL_Interrupt_Ethernet.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/*Common Module Specific Sample Program include files*/
#include "nai_ttl_int.h"
#include "nai_ttl_cfg.h"
#include "nai_ttl_int_ether.h"

/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#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"

/* Module Specific NAI Board Library files */
#include "functions/naibrd_ttl.h"

IDRConfig inputIDRConfig;
InterruptConfig inputInterruptConfig;
etherIntFuncDef ttlEtherIntFunc;
ClearInterrupt TTL_ClearInterrupt;
bool_t bDisplayEtherUPR;

/* Extern Functions or Variables*/
extern TtlConfig inputTTLConfig;

/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/

static const int8_t *CONFIG_FILE = (int8_t *)"default_TTL_Interrupt.txt";

/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_TTL_Interrupt_Ethernet();

static uint8_t DEF_RX_RESPONSE_IPv4_ADDR[] =   {192,168,1,100};
static uint8_t COMMANDS[MAX_ETHER_IDR_CMD_CNT*MAX_ETHER_BLOCK_REG_CNT];

/**************************************************************************************************************/
/*****                                     Main Routine                                                   *****/
/**************************************************************************************************************/
/**************************************************************************************************************/
/**
<summary>

The main routine assists in gaining access to the board.

The following routines from the nai_sys_cfg.c file are
called to assist with accessing and configuring the board.

 - ConfigDevice
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - CheckModule

</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t TTL_Interrupt_Ethernet(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   initializeTTLConfigurations(0, 0, 0, 0, 0, 0);
   initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, NAIBRD_INT_STEERING_ON_BOARD_1, 0, 0);
   initializeIDRConfigurations(0, 0, DEF_RX_RESPONSE_PROTOCOL, DEF_RX_RESPONSE_PORT, DEF_RX_RESPONSE_IPv4_ADDR, DEF_RX_RESPONSE_IPv4_LENGTH, COMMANDS, 0, 0, DEF_ETHERNET_TTL_LOHI_IDR_ID);

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         inputTTLConfig.cardIndex = cardIndex;
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            inputTTLConfig.module = module;
            if (stop != TRUE)
            {
               inputTTLConfig.modid = naibrd_GetModuleID(cardIndex, module);
               if ((inputTTLConfig.modid != 0))
               {
                  Run_TTL_Interrupt_Ethernet();
               }
            }
         }
         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}
/**************************************************************************************************************/
/**
<summary>
This function is broken into the following major steps. These steps correspond with the steps provided
in the naibrd SSK Quick Guide(Interrupts) file.

2a. Ethernet Interrupt Handling - Setup IDR to handle interrupt

   API CALLS - naibrd_Ether_SetIDRConfig, naibrd_Ether_StartIDR,naibrd_Ether_ClearIDRConfig

3. Enable Module Interrupts- Configures module to interrupt when channel receives TTL message.

   API CALLS - naibrd_TTL_SetInterruptEdgeLevel, naibrd_TTL_SetIntVector, naibrd_TTL_SetInterruptSteering, naibrd_TTL_SetIntEnable

4. Not applicable to this module

5. Show Interrupt Handling - The IDR server will listen on the boards ports for IDRs indicating an interrupt.
   These results will be decoded and displayed to the user.

6. Re-arming Interrupts - Clear the status register to allow interrupts to occur again. This is done by writing to the status register.
   In this program, the write command is included in the IDR.

   API CALLS - nai_ether_BeginWriteMessage, nai_ether_WriteMessageData, nai_ether_FinishMessage

7. Clear Module Configurations

   API CALLS - naibrd_TTL_SetRxEnable, naibrd_TTL_ClearStatus

8. Clear Board Configurations

   API CALLS - naibrd_Ether_StopIDR, naibrd_Ether_ClearIDRConfig

</summary>
*/
/**************************************************************************************************************/
static bool_t Run_TTL_Interrupt_Ethernet()
{
   bool_t bQuit = FALSE;
   bool_t bGen4ttlIDRCommands;
   int32_t maxChannel = naibrd_TTL_GetChannelCount(inputTTLConfig.modid);
   int32_t minChannel = 1;

    bGen4ttlIDRCommands = SupportsGen4Ether(inputTTLConfig.cardIndex);

    if(!bGen4ttlIDRCommands)
   {
         printf("TTL Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n");
         bQuit = TRUE;
   }
   if(!bQuit){
      bQuit = naiapp_query_ChannelNumber(maxChannel,minChannel,&inputTTLConfig.channel);
      inputTTLConfig.maxChannel = inputTTLConfig.channel;
      inputTTLConfig.minChannel = inputTTLConfig.channel;
   }
   if(!bQuit){
      bQuit = QueryIDRConfigInformation(&inputIDRConfig);
   }
   if(!bQuit){
      bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
   }
   if(!bQuit)
   {
      bQuit = QueryUserForEtherIDRMsgDisplay(&bDisplayEtherUPR);
   }

   if (!bQuit)
   {
      /****2. Setup IDR to Handle Interrupt (also contains step 6) ****/
      if(inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
      {
         inputIDRConfig.cardIndex = inputTTLConfig.cardIndex;
         inputIDRConfig.boardInterface =  NAI_INTF_ONBOARD;
         inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
      }
      else /*OffBoard Interrupt*/
      {
         inputIDRConfig.cardIndex = 0;
         inputIDRConfig.boardInterface = NAI_INTF_PCI;
         inputInterruptConfig.steering =  NAIBRD_INT_STEERING_CPCI_APP;
      }
      setupIDRConfiguration_TTL(inputTTLConfig,&inputIDRConfig,bGen4ttlIDRCommands);
      check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
      check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex,(uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));

      /****3. configure module To Interrupt****/
      configureTTLToInterrupt(inputInterruptConfig,inputTTLConfig);
      enableTTLInterrupts(inputTTLConfig,TRUE);

      /****5. Show Interrupt Handling****/
      TTL_ClearInterrupt = ClearInterrupt_TTL;
      ttlEtherIntFunc = HandleTTLEtherInterrupt;
      bQuit = runIDRServer(inputIDRConfig);

      /***** 7. Clear Module Configurations *****/
      enableTTLInterrupts(inputTTLConfig,FALSE);

      /*****8. Clear Board Configurations *****/
      check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
      check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
      check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));
      check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));

   }

   return bQuit;

}
Full Source — nai_ttl_int.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>

/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#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"

/* Common TTL Sample Program include files */
#include "nai_ttl_int.h"
#include "nai_ttl_cfg.h"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "naibrd_ether.h"
#include "functions/naibrd_ttl.h"
#include "maps/nai_map_ttl.h"

bool_t interruptOccured; /* used by checkForInterrupt to see if interrupt occurred */
int32_t frameCount;	/* counter increment when frames are found */
uint32_t interruptVector; /* used by checkForInterrupt to get vector of the interrupt that occurred in myIsr */

/* Extern Functions or Variables*/
extern InterruptConfig inputInterruptConfig;
extern TtlConfig inputTTLConfig;

/**************************************************************************************************************/
/**
<summary>
This function configures an interrupt to occur when a message is received on any of the ttl channels.
</summary>
*/
/**************************************************************************************************************/
void configureTTLToInterrupt(InterruptConfig inputInterruptConfig, TtlConfig inputTTLConfig)
{

   int32_t cardIndex = inputTTLConfig.cardIndex;
   int32_t module = inputTTLConfig.module;
   int32_t interrupt_Edge_Trigger = inputInterruptConfig.interrupt_Edge_Trigger;
   int32_t steering = inputInterruptConfig.steering;
   uint32_t rawstatus = 0;
   int32_t chan;

   enableTTLInterrupts(inputTTLConfig, FALSE);

   /* Clear the Interrupt Status (Read the status and write back "1" to statuses which are set to clear the status) */
   check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
   check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, rawstatus));
   check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
   check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, rawstatus));
   check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_BIT_LATCHED, &rawstatus));
   check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_BIT_LATCHED, rawstatus));

   /* Setup the Interrupt Vector - map to the same vector */
   check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, NAI_TTL_LOHI_INTERRUPT_VECTOR));
   check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, NAI_TTL_HILO_INTERRUPT_VECTOR));
   check_status(naibrd_TTL_SetGroupInterruptVector(cardIndex, module, 1, NAI_TTL_STATUS_BIT_LATCHED, NAI_TTL_BIT_INTERRUPT_VECTOR));

   /* Setup the Latched Status Mode */

   for (chan = 1; chan <= inputTTLConfig.maxChannel; chan++)
   {
      check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
      check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
      check_status(naibrd_TTL_SetEdgeLevelInterrupt(cardIndex, module, chan, NAI_TTL_STATUS_BIT_LATCHED, (nai_ttl_interrupt_t)interrupt_Edge_Trigger));
   }

   check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, steering));
   check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, steering));
   check_status(naibrd_TTL_SetGroupInterruptSteering(cardIndex, module, 1, NAI_TTL_STATUS_BIT_LATCHED, steering));

}

/**************************************************************************************************************/
/**
<summary>
Enables the channels within the (minChannel,maxChannel) range to interrupt
if enable is true and disables them otherwise.
</summary>
*/
/**************************************************************************************************************/
void enableTTLInterrupts(TtlConfig inputTTLConfig, bool_t enable) {
   int32_t channel;
   for (channel = inputTTLConfig.minChannel; channel <= inputTTLConfig.maxChannel; channel++)
   {
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex, inputTTLConfig.module, channel, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, enable));
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex, inputTTLConfig.module, channel, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, enable));
      check_status(naibrd_TTL_SetInterruptEnable(inputTTLConfig.cardIndex, inputTTLConfig.module, channel, NAI_TTL_STATUS_BIT_LATCHED, enable));
   }
}

/**************************************************************************************************************/
/**
<summary>
The routine is called to handle a interrupt. This function alerts checkForInterrupt that an interrupt has occurred.
In vxWorks you must clear the Interrupt on the board within the ISR.
</summary>
*/
/**************************************************************************************************************/

#if defined (__VXWORKS__)
void basic_ISR_TTL(uint32_t param)
#else
void basic_ISR_TTL(void *param, uint32_t vector)
#endif
{
   interruptOccured = TRUE;

#if defined (__VXWORKS__)
   interruptVector = nai_Onboard_GetInterruptVector();
   nai_Onboard_ClearInterrupt();
#elif defined (WIN32)
   UNREFERENCED_PARAMETER(param);
   interruptVector = vector;
#else
   interruptVector = vector;
#endif
}
/**************************************************************************************************************/
/**
<summary>
Prompts user to check if an interrupt has occurred. MyIsr() should be installed if using this function.
</summary>
*/
/**************************************************************************************************************/
bool_t checkForTTLInterrupt(TtlConfig inputTTLConfig) {
   bool_t bQuit;
   int32_t cardIndex;
   int32_t module;
   uint32_t rawstatus = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   cardIndex = inputTTLConfig.cardIndex;
   module = inputTTLConfig.module;
   bQuit = FALSE;
   interruptOccured = FALSE;
   while (!bQuit) {
      printf("\nPress enter to check if Lo-Hi or Hi-Lo interrupt Occurred (press Q to quit):");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit) {
         if (interruptOccured) {
            switch (interruptVector)
            {
               case NAI_TTL_LOHI_INTERRUPT_VECTOR:
                  printf("\nLo-Hi Interrupt Occurred");
                  check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
                  break;
               case NAI_TTL_HILO_INTERRUPT_VECTOR:
                  printf("\nHi-Lo Interrupt Occurred");
                  check_status(naibrd_TTL_GetGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
                  break;
            }

            printf("\nVector = %#x \n", interruptVector);
            printf("Status = %#x \n", rawstatus);
            interruptOccured = FALSE;
         }
         else {
            printf("\nNo Interrupt Occurred");
         }
         printf("\n\nWould you like to clear the status register? (default:N):");

         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

         if (inputBuffer[0] == 'y' || inputBuffer[0] == 'Y')
         {
            switch (interruptVector)
            {
               case NAI_TTL_LOHI_INTERRUPT_VECTOR:
                  check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, rawstatus));
                  break;
               case NAI_TTL_HILO_INTERRUPT_VECTOR:
                  check_status(naibrd_TTL_ClearGroupStatusRaw(cardIndex, module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, rawstatus));
                  break;
            }
         }
      }
   }
   return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
GetTTLLatchStatusTriggerMode handles prompting the user for the trigger mode for the latched status register
(Edge Triggered or Level Triggered).
</summary>
*/
/**************************************************************************************************************/
bool_t GetTTLLatchStatusTriggerMode(int32_t* interrupt_Edge_Trigger)
{
   bool_t bQuit;
   uint32_t temp;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter Latched Status Trigger Mode (Edge=0, Level=1) (Default=0): ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         temp = (int32_t)atol((const char*)inputBuffer);

         if (temp == 0 || temp == 1)
         {
            *interrupt_Edge_Trigger = temp;
         }
         else
         {
            printf("ERROR: Invalid Interrupt Trigger Mode.\n");
         }
      }
      else
         *interrupt_Edge_Trigger = 0;
   }
   return(bQuit);
}

/**************************************************************************************************************/
/**
<summary>
This routine takes in the vector of the TTL RX interrupt that has just occurred. And gets the status, fifo status,
and fifo data of all channels that interrupted, and prints it.
</summary>
*/
/**************************************************************************************************************/
void handleTTLInterrupt(uint32_t nVector) {

   uint32_t rawstatus = 0;

   printf("\n\nInterrupt Occurred \n\n");
   if (inputInterruptConfig.bPromptForInterruptClear)
   {
      promptUserToClearInterrupt_TTL();
   }

   switch (nVector)
   {
      case NAI_TTL_LOHI_INTERRUPT_VECTOR:
         printf("LoHi Transition Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, rawstatus));
         break;
      case NAI_TTL_HILO_INTERRUPT_VECTOR:
         printf("HiLo Transition Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, rawstatus));
         break;
      case NAI_TTL_BIT_INTERRUPT_VECTOR:
         printf("BIT Interrupt\n");
         check_status(naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_BIT_LATCHED, &rawstatus));
         check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_BIT_LATCHED, rawstatus));
         break;
   }
   printInterruptInformation_TTL(nVector, rawstatus, FALSE);
}
void promptUserToClearInterrupt_TTL()
{
   /* Prompt the user to clear the interrupt received */
   SetUserRequestClearInt(FALSE);
   printf("\n");
   DisplayMessage_TTLInterrupt(MSG_USER_CLEAR_TTL_INT);

   /* Wait for the user to respond */
   while (!GetUserRequestClearInt())
   {
      nai_msDelay(10);
   }
}
/**************************************************************************************************************/
/**
<summary>
DisplayMessage_TTLInterrupt handles displaying the messages associated with the msgId passed in.
</summary>
*/
/**************************************************************************************************************/

void DisplayMessage_TTLInterrupt(int32_t msgId)
{
   switch (msgId)
   {
      case (int32_t)MSG_BANNER_TTL_INT:
      {
         printf("\n********************************************************************************");
         printf("\n******                        TTL INTERRUPT                               ******");
         printf("\nAn interrupt will occur when the TTL Module receives an interrupt status  ");
         printf("\n********************************************************************************");
      }
      break;

      case (int32_t)MSG_USER_TRIGGER_TTL_INT:
      {
         printf("\nPress \"Q\" to quit the application.\nPlease trigger TTL Lo-Hi,Hi-Lo or BIT status interrupt:");
      }
      break;

      case (int32_t)MSG_USER_CLEAR_TTL_INT:
      {
         printf("Press \"C\" to clear interrupts... ");
      }
      break;
   }
}
/**************************************************************************************************************/
/**
<summary>
Function will print the Data provided for each channel that has been set in the status register.
It will also print the status and idr id or vector.
</summary>
*/
/**************************************************************************************************************/

void printInterruptInformation_TTL(int32_t interruptID, uint32_t status, bool_t isEther)
{
   printf("-----------------------------------\n");
   if (isEther)
      printf("\nIDR ID = %#x \n", interruptID);
   else
      printf("\nVector = %#x \n", interruptID);
   printf("Status = %#x \n", status);
}

void ClearInterrupt_TTL()
{
   uint32_t status;
   if (inputInterruptConfig.bPromptForInterruptClear)
   {
      promptUserToClearInterrupt_TTL();
   }
   naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &status);
   naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, status);
   naibrd_TTL_GetGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &status);
   naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, status);
}
Full Source — nai_ttl_int_ether.c (SSK 1.x)
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#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"

/* Common TTL Sample Program include files */
#include "nai_ttl_int_ether.h"
#include "nai_ttl_cfg.h"

/* naibrd include files */
#include "functions/naibrd_ttl.h"
#include "maps/nai_map_ttl.h"
#include "advanced/nai_ether_adv.h"

int32_t command_index_interrupt_status;

/* Extern Functions or Variables*/
extern TtlConfig inputTTLConfig;

/**************************************************************************************************************/
/**
<summary>
Constructs the ethernet commands that are part of the IDR. Configures the IDR on the board.
</summary>
*/
/**************************************************************************************************************/
void setupIDRConfiguration_TTL(TtlConfig inputTTLConfig, IDRConfig* inputIDRConfig, bool_t bGen4TTLIDRCommands) {

   int32_t cardIndex = inputIDRConfig->cardIndex;
   uint16_t protocol = inputIDRConfig->protocol;
   uint16_t port = inputIDRConfig->port;
   uint8_t* ipAddress = inputIDRConfig->ipAddress;
   uint8_t ipLength = inputIDRConfig->ipLength;

   int32_t vector1 = NAI_TTL_LOHI_INTERRUPT_VECTOR;
   int32_t vector2 = NAI_TTL_HILO_INTERRUPT_VECTOR;
   uint8_t *commands = inputIDRConfig->commands;
   uint16_t *cmdcount = &inputIDRConfig->cmdcount;
   uint16_t *cmdlength = &inputIDRConfig->cmdlength;

   uint32_t addr = NAI_TTL_GEN5_REG_LO_HI_TRANS_LATCHED_STATUS_ADD;

   check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID));
   InitTTLIDRCommands(inputTTLConfig, inputIDRConfig, bGen4TTLIDRCommands, addr);
   check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_TTL_LOHI_IDR_ID, protocol, ipLength, ipAddress, port, vector1, *cmdcount, *cmdlength, commands));
   check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID));
   check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_TTL_HILO_IDR_ID, protocol, ipLength, ipAddress, port, vector2, *cmdcount, *cmdlength, commands));

}
/**************************************************************************************************************/
/**
<summary>
This function configures the IDR (Interrupt Driven Response) commands when a TTL Rx interrupt occurs.
There are four Ethernet commands that will be processed by the board when a TTL Rx interrupt occurs.

</summary>
*/
/**************************************************************************************************************/
void InitTTLIDRCommands(TtlConfig inputTTLConfig, IDRConfig* inputIDRConfig, bool_t bGen4TTLIDRCommands, uint32_t addr)
{
   nai_status_t status = NAI_SUCCESS;

   uint16_t msgIndex = 0;
   uint32_t boardAddress;
   uint32_t moduleOffset;

   boardAddress = 0;

   status = check_status(naibrd_GetModuleOffset(inputTTLConfig.cardIndex, inputTTLConfig.module, &moduleOffset));
   if (status == NAI_SUCCESS)
      status = check_status(naibrd_GetAddress(inputTTLConfig.cardIndex, &boardAddress));

   if (status == NAI_SUCCESS)
   {
      if (bGen4TTLIDRCommands)
      {
         msgIndex = inputIDRConfig->cmdlength;
         MakeTTLReadRegsCommand(inputIDRConfig, boardAddress, moduleOffset, bGen4TTLIDRCommands, msgIndex, addr);
      }
   }
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read reg command and stores it in the IDR Configuration. The read will be performed
on the modules latched status interrupt register. This function will read two registers based on the stride being set to
16 and addr being set to the first register that needs to be read
</summary>
*/
/**************************************************************************************************************/
void MakeTTLReadRegsCommand(IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex, uint32_t addr)
{

   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;

   if (bGen4Ether)
   {
      seqno = 0;
      addr = boardAddress + moduleOffset + addr;
      count = TTL_INTERRUPT_RESPONSE_REG_COUNT;
      stride = 16;

      msgIndex = (uint16_t)nai_ether_MakeReadMessage(&inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, addr, stride, count, NAI_REG32);
      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      command_index_interrupt_status = inputIDRConfig->cmdcount;
      inputIDRConfig->cmdcount++;
   }
}
/**************************************************************************************************************/
/**
<summary>
HandleTTLEtherInterrupt is called by the decodeUPRIDRMessages() routine in nai_sys_int_ether.c when an
unprompted (UPR) Ethernet message is received with the TDR/IDR Index equal to DEF_ETHERNET_DT_IDR_ID.
This routine will parse the message to retrieve the information requested in the SetupDTEtherIDRconfig()
routine.
</summary>
*/
/**************************************************************************************************************/
void HandleTTLEtherInterrupt(uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id)
{
   uint16_t seq;
   nai_ether_typecode_t tc;
   nai_ether_gen_t gen = NAI_ETHER_GEN4;
   int32_t size;
   int32_t offset;
   uint16_t datacnt = 0;
   uint32_t data;
   uint32_t ttlstatus_int[TTL_INTERRUPT_RESPONSE_REG_COUNT];
   nai_ttl_status_type_t ttl_status_type = NAI_TTL_STATUS_BIT_LATCHED;
   int32_t i;
   offset = nai_ether_DecodeMessageHeader(msg, msglen, &seq, &tc, gen, &size);

   switch (tc)
   {
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
         datacnt = (msglen - 10) / NAI_REG32;
         for (i = 0; i < datacnt; i++)
         {
            data = 0;
            data = msg[offset++] << 24;
            data |= msg[offset++] << 16;
            data |= msg[offset++] << 8;
            data |= msg[offset++];
            if (i < TTL_INTERRUPT_RESPONSE_REG_COUNT)
               ttlstatus_int[i] = data;
         }
         break;
   }
   printf("\n\n");
   printf("IDR ID : %d\n", tdr_idr_id);

   if (datacnt == TTL_INTERRUPT_RESPONSE_REG_COUNT)
   {

      for (i = 0; i < TTL_INTERRUPT_RESPONSE_REG_COUNT; i++)
      {
         switch (i)
         {
            case 0:
               ttl_status_type = NAI_TTL_STATUS_LO_HI_TRANS_LATCHED;
               break;
            case 1:
               ttl_status_type = NAI_TTL_STATUS_HI_LO_TRANS_LATCHED;
               break;
         }
         if (ttlstatus_int[i] != 0)
         {
            switch (i)
            {
               case 0:
                  printf("Received TTL Lo-Hi Interrupt: (Interrupt_status) 0x%08X\n", ttlstatus_int[i]);
                  break;
               case 1:
                  printf("Received TTL Hi-Lo Interrupt: (Interrupt_status) 0x%08X\n", ttlstatus_int[i]);
                  break;
            }

            check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, ttl_status_type, ttlstatus_int[i]));
            switch (i)
            {
               case 0:
                  printf("Cleared TTL Lo-Hi Interrupt: 0x%08X\n", ttlstatus_int[i]);
                  break;
               case 1:
                  printf("Cleared TTL Hi-Lo Interrupt: 0x%08X\n", ttlstatus_int[i]);
                  break;
            }
         }
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet write reg command and stores it in the IDR Configuration. The write will be performed
on the modules latched status interrupt register. The purpose of this write is to clear the interrupt status register and re-arm the interrupts
after one has occurred.
</summary>
*/
/**************************************************************************************************************/
void MakeTTLWriteRegsCommand(TtlConfig inputTTLConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex)
{

   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;
   uint32_t regaddr;
   uint32_t data = 0x1 << (inputTTLConfig.channel - 1);   /* Clear Rx interrupt bits */
   uint32_t addr = NAI_TTL_GEN5_REG_BIT_LATCHED_STATUS_ADD;

   if (bGen4Ether)
   {

      seqno = 0;
      regaddr = boardAddress + moduleOffset + addr;
      count = 1;
      stride = 4;

      msgIndex = (uint16_t)nai_ether_BeginWriteMessage(&inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, regaddr, stride, count, NAI_REG32);
      if (msgIndex >= 0)
      {
         msgIndex = (uint16_t)nai_ether_WriteMessageData(&inputIDRConfig->commands[startIndex], msgIndex, NAI_REG32, &data, NAI_REG32, count);

         if (msgIndex >= 0)
         {
            msgIndex = (uint16_t)nai_ether_FinishMessage(&inputIDRConfig->commands[startIndex], msgIndex, NAI_ETHER_GEN4);
         }
      }
      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      inputIDRConfig->cmdcount++;
   }
}

Help Bot

X