TTL Interrupt Ethernet Sample Application (SSK 1.x)
Overview
The TTL Interrupt Ethernet sample application delivers the same TTL (Transistor-Transistor Logic) transition interrupts as TTL Interrupt Basic and TTL Interrupt, but over Ethernet instead of a host bus interrupt line. It does this with the board’s IDR (Interrupt-Driven Response) feature.
The idea behind an IDR: rather than the host installing an ISR and waiting for a bus interrupt, you preload the board with a small set of Ethernet commands and tie them to a module interrupt. When the module interrupts (a logic transition), the board executes those commands on its own and sends an unprompted Ethernet message to the host. The host runs an IDR server that listens for those messages, decodes them, and reports which channels transitioned.
Because of this, the flow differs from the bus-interrupt samples in a few key ways:
- there is no
naibrd_InstallISR()— the “handler” is the IDR the board runs itself; - the interrupt is configured with
naibrd_Ether_SetIDRConfig()/naibrd_Ether_StartIDR()instead of an ISR install; - the module is still armed with the same
configureTTLToInterrupt()/enableTTLInterrupts()helpers used by the Basic sample; - results arrive as decoded Ethernet messages handled by
HandleTTLEtherInterrupt().
Important
This sample requires Generation 4 (or later) Ethernet command support. On startup it calls
SupportsGen4Ether()and refuses to run on pre-Gen 4 Ethernet: “TTL Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported.”
Prerequisites
Before running this sample, make sure you have:
- An NAI board with a TTL module and Gen 4 (or later) Ethernet support.
- A network path from the board to the host that will run the IDR server, with the host’s IP address and port known.
- SSK 1.x installed on your development host, with the sample applications built.
- A way to drive logic transitions on the selected channel.
How to Run
Launch the TTL_Interrupt_Ethernet 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 presents an interactive board menu where you configure a board connection, card index, and module slot. After selecting the module you provide the IDR/response details (IP, port), choose onboard or offboard processing, then trigger transitions and watch the IDR server report them.
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.
main() initializes the shared TTL, interrupt, and IDR configuration structures before the standard board menu / card / module selection:
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);DEF_RX_RESPONSE_IPv4_ADDR defaults to 192.168.1.100; COMMANDS is the byte buffer the IDR commands are built into. The selected card, module, and module ID are stored in the shared inputTTLConfig structure, and Run_TTL_Interrupt_Ethernet() takes over.
Important
Common connection errors you may encounter at this stage:
- No board found / connection timeout — verify the board is powered and connected; check the configuration file or reconfigure in the board menu.
- Pre-Gen 4 Ethernet — this sample requires Gen 4 Ethernet; it will report the limitation and quit.
- No IDR ever arrives — confirm the response IP/port point at the host running the IDR server, and that no firewall is dropping the board’s unprompted messages. See the troubleshooting table below.
How Ethernet (IDR) Interrupts Differ
Run_TTL_Interrupt_Ethernet() first confirms Gen 4 Ethernet, gathers the channel and IDR settings, sets up and starts the IDR, arms the module, and then runs the IDR server:
bGen4ttlIDRCommands = SupportsGen4Ether(inputTTLConfig.cardIndex);
if (!bGen4ttlIDRCommands)
{
printf("TTL Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n");
bQuit = TRUE;
}
/* Query channel, IDR config info, onboard/offboard, and message display options ... */
if (!bQuit)
{
/* Onboard vs offboard selects the interface and steering used for the IDR */
if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
inputIDRConfig.cardIndex = inputTTLConfig.cardIndex;
inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else /* offboard */
{
inputIDRConfig.cardIndex = 0;
inputIDRConfig.boardInterface = NAI_INTF_PCI;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
}
/* 2. Set up and start the IDR (contains re-arm) */
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. Arm the module (shared helpers, same as Basic) */
configureTTLToInterrupt(inputInterruptConfig, inputTTLConfig);
enableTTLInterrupts(inputTTLConfig, TRUE);
/* 5. Run the IDR server until the user quits */
TTL_ClearInterrupt = ClearInterrupt_TTL;
ttlEtherIntFunc = HandleTTLEtherInterrupt;
bQuit = runIDRServer(inputIDRConfig);
/* 7 & 8. Disable interrupts and tear down both IDRs */
enableTTLInterrupts(inputTTLConfig, FALSE);
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));
}The sample uses two IDR IDs — one for the low-to-high transition (DEF_ETHERNET_TTL_LOHI_IDR_ID) and one for high-to-low (DEF_ETHERNET_TTL_HILO_IDR_ID) — so the host can tell which kind of transition fired from the IDR ID alone.
Setting Up the IDR
setupIDRConfiguration_TTL() (in nai_ttl_int_ether.c) builds the Ethernet command that reads the module’s latched-status registers, then registers it as an IDR for each transition type:
/* Clear any prior config, build the read command, then register the IDR */
naibrd_Ether_ClearIDRConfig(cardIndex, DEF_ETHERNET_TTL_LOHI_IDR_ID);
InitTTLIDRCommands(inputTTLConfig, inputIDRConfig, bGen4TTLIDRCommands, addr);
naibrd_Ether_SetIDRConfig(cardIndex, DEF_ETHERNET_TTL_LOHI_IDR_ID, protocol, ipLength, ipAddress, port, vector1, *cmdcount, *cmdlength, commands);
naibrd_Ether_ClearIDRConfig(cardIndex, DEF_ETHERNET_TTL_HILO_IDR_ID);
naibrd_Ether_SetIDRConfig(cardIndex, DEF_ETHERNET_TTL_HILO_IDR_ID, protocol, ipLength, ipAddress, port, vector2, *cmdcount, *cmdlength, commands);nai_status_t naibrd_Ether_ClearIDRConfig(int32_t cardIndex, uint16_t idrid)— clears any existing configuration for the given IDR id.nai_status_t naibrd_Ether_SetIDRConfig(int32_t cardIndex, uint16_t idrid, uint16_t protocol, uint16_t iplen, uint8_t ip[], uint16_t port, uint32_t vector, uint16_t count, uint32_t arraysize, uint8_t command[])— registers an IDR: when the associated interrupt (vector) fires, the board runs thecommandbyte array (countcommands,arraysizebytes) and sends the response toip:portusingprotocol.nai_status_t naibrd_Ether_StartIDR(int32_t cardIndex, uint16_t idrid)— arms the IDR so the board begins acting on it.
The command itself is a read of the module’s Lo-Hi and Hi-Lo latched-status registers, built by MakeTTLReadRegsCommand() using nai_ether_MakeReadMessage() with a stride of 16 so a single command reads both registers. That read response is what the host decodes to learn which channels transitioned.
Arming the Module
Once the IDR is running, the module is armed to interrupt with the same shared helpers used by TTL Interrupt Basic — configureTTLToInterrupt() and enableTTLInterrupts(). See the TTL Interrupt Basic guide for the full walkthrough; the naibrd_TTL_*() calls (all on group 1) are:
nai_status_t naibrd_TTL_SetGroupInterruptVector(int32_t cardIndex, int32_t module, int32_t group, nai_ttl_status_type_t type, uint32_t vector)— maps each transition type to a vector (these vectors are what the IDRs are keyed to).nai_status_t naibrd_TTL_SetEdgeLevelInterrupt(int32_t cardIndex, int32_t module, int32_t channel, nai_ttl_status_type_t type, nai_ttl_interrupt_t interruptType)— edge vs level per channel.nai_status_t naibrd_TTL_SetGroupInterruptSteering(int32_t cardIndex, int32_t module, int32_t group, nai_ttl_status_type_t type, naibrd_int_steering_t steering)— steers the interrupt (onboard vs the CPCI application path, matching the onboard/offboard choice).nai_status_t naibrd_TTL_SetInterruptEnable(int32_t cardIndex, int32_t module, int32_t channel, nai_ttl_status_type_t type, bool_t enable)— arms/disarms the channel.
Receiving and Handling the Interrupt
runIDRServer() listens for the board’s unprompted IDR messages. Each time one arrives it invokes the registered callback HandleTTLEtherInterrupt(), which decodes the message, prints which channels transitioned, and clears the latched status to re-arm:
void HandleTTLEtherInterrupt(uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id)
{
/* ... decode the read-response message into ttlstatus_int[] ... */
/* For each non-zero status word, report and clear (re-arm) that transition type */
check_status(naibrd_TTL_ClearGroupStatusRaw(inputTTLConfig.cardIndex, inputTTLConfig.module, 1, ttl_status_type, ttlstatus_int[i]));
}nai_status_t naibrd_TTL_ClearGroupStatusRaw(int32_t cardIndex, int32_t module, int32_t group, nai_ttl_status_type_t type, uint32_t statusRaw)— clears the latched status bits reported in the IDR response, re-arming the interrupt so the next transition is delivered.
The IDR ID (tdr_idr_id) and the decoded status words tell the host which transition type fired and on which channels. The message decode uses the common Ethernet helpers (nai_ether_DecodeMessageHeader() and friends).
Note
This sample re-arms host-side: the host receives the read-response IDR and then issues
naibrd_TTL_ClearGroupStatusRaw()itself. The helpernai_ttl_int_ether.calso definesMakeTTLWriteRegsCommand(), which can build a write command into the IDR so the board clears its own status as part of the response — an alternative re-arm strategy not exercised in this sample’s default path.
Tearing Down
On quit, the sample disables the channel interrupts and stops and clears both IDRs:
nai_status_t naibrd_Ether_StopIDR(int32_t cardIndex, uint16_t idrid)— stops the board acting on the IDR.naibrd_Ether_ClearIDRConfig()— removes the IDR configuration.
Both the Lo-Hi and Hi-Lo IDR IDs are stopped and cleared so no stale configuration remains on the board.
Troubleshooting Reference
This table summarizes common errors and symptoms covered above. Consult your module’s manual and the naibrd SSK Quick Guide (Interrupts) for more detail.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
| ”…Prior to Generation 4 Ethernet…not supported” | Board’s Ethernet is pre-Gen 4 | This sample requires Gen 4 Ethernet; use a bus-interrupt sample (TTL Interrupt) on older hardware. |
| No IDR message reaches the host | Wrong response IP/port, or firewall dropping unprompted messages | Confirm the response IP/port target the IDR-server host; allow the board’s inbound Ethernet messages through any firewall. |
| Interrupt fires once, then stops | Latched status not cleared | Ensure HandleTTLEtherInterrupt() runs and calls naibrd_TTL_ClearGroupStatusRaw(); check the decoded status is non-zero. |
| Cannot tell Lo-Hi from Hi-Lo | Reading only one IDR | Both DEF_ETHERNET_TTL_LOHI_IDR_ID and DEF_ETHERNET_TTL_HILO_IDR_ID are started; the IDR ID identifies the transition type. |
| Onboard vs offboard confusion | Interface/steering mismatch | Onboard uses NAI_INTF_ONBOARD + NAIBRD_INT_STEERING_ON_BOARD_1; offboard uses NAI_INTF_PCI + NAIBRD_INT_STEERING_CPCI_APP. Pick the one matching your setup. |
Full Source
The top-level sample source is shown first, followed by the Ethernet IDR helper routines and the shared module-arming helpers it calls.
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"
/*********************************************/
/* 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 *****/
/**************************************************************************************************************/
#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;
}Ethernet IDR helpers — nai_ttl_int_ether.c (SSK 1.x)
/**************************************************************************************************************/
/* setupIDRConfiguration_TTL: build the read command and register/clear the Lo-Hi and Hi-Lo IDRs. */
/**************************************************************************************************************/
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));
}
/**************************************************************************************************************/
/* InitTTLIDRCommands / MakeTTLReadRegsCommand: build the Ethernet read of the latched-status registers. */
/**************************************************************************************************************/
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 = 0;
uint32_t moduleOffset;
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);
}
}
}
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)
{
/* stride 16 + base addr at Lo-Hi latched status reads both the Lo-Hi and Hi-Lo status registers */
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++;
}
}
/**************************************************************************************************************/
/* HandleTTLEtherInterrupt: called by the IDR server per received message -- decode, report, and re-arm. */
/**************************************************************************************************************/
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);
/* Check to make sure we got all 4 status elements (BIT, Lo-Hi, Hi-Lo, Overcurrent) */
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;
}
}
}
}
}Shared module-arming helpers — nai_ttl_int.c (SSK 1.x, relevant routines)
/**************************************************************************************************************/
/* configureTTLToInterrupt: program the module to interrupt on a logic transition (or BIT) for the group. */
/**************************************************************************************************************/
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 stale latched status before arming */
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));
/* Map each transition type to an interrupt 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));
/* Edge/level mode for each channel in range */
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));
}
/**************************************************************************************************************/
/* enableTTLInterrupts: enable/disable interrupt generation for each channel in the configured range. */
/**************************************************************************************************************/
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));
}
}