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

nai ar int

nai ar int

Explanation

About the Sample Application Code

This sample C application code from North Atlantic Industries (NAI) demonstrates how to interact with their embedded function modules using their Software Starter Kit (SSK). The application involves handling interrupts on AR (Acquisition and Recording) channels, prompted by received messages. Below is an explanation of the code structure and functionality:

Includes and Definitions

The code includes several NAI-specific headers required to interface with the boards and handle interrupts: - naiapp_interrupt.h, naiapp_interrupt_ether.h: Interrupt handling. - naiapp_boardaccess_query.h, naiapp_boardaccess_access.h, naiapp_boardaccess_display.h, naiapp_boardaccess_utils.h: Board access utilities, display, and query functionalities. - nai_ar_int.h, nai_ar_cfg.h: AR-specific configuration and interrupt handling. - nai.h, naibrd.h, naibrd_ether.h: General board definitions and Ethernet handling. - functions/naibrd_ar.h, maps/nai_map_ar.h: Specific AR function mappings and AR board definitions.

Function Prototypes

Function prototypes specify the functions used in this program: - void promptUserToClearInterrupt_AR()

Function Implementations

checkForARInterrupt

This function periodically prompts the user to check if an interrupt has occurred on a specific AR channel. It involves: 1. Reading status and buffer counts if an interrupt is detected. 2. Extracting FIFO data, status, and timestamps. 3. Displaying the retrieved data. 4. Optionally clearing the status register based on user input.

configureARToInterruptOnRx

This function configures an interrupt to trigger on receiving a message on a specific AR channel: 1. Clearing previous interrupt settings. 2. Setting the interrupt vector, edge/level trigger, and steering configuration.

configureARToInterruptOnRxMultiChan

Similar to configureARToInterruptOnRx, but enables interrupts for multiple AR channels within a specified range.

DisplayMessage_ARInterrupt

A utility function to print messages related to AR interrupt handling, based on a msgId.

enableARInterrupts

This function enables or disables interrupts on specified AR channels based on the enable parameter.

GetARLatchStatusTriggerMode

Prompts the user to specify the trigger mode (Edge or Level) for the latched status register.

basic_ISR_AR

Defines the Interrupt Service Routine (ISR) called when an interrupt occurs: 1. Sets the interruptOccured flag to TRUE. 2. Depending on the OS (VXWorks, Windows), it may clear the interrupt on the board.

handleARInterrupt

Handles the AR RX interrupt: 1. Retrieves status, FIFO counts, and data from all channels that triggered the interrupt. 2. Displays the gathered information or logs to a specified stream.

printInterruptInformation_AR

Prints detailed information related to an interrupt for each AR channel: 1. Extracts and prints message status, data, and timestamps from the FIFO.

promptUserToClearInterrupt_AR

Prompts the user to clear the received interrupt.

QueryUserForTimeStampEnable

Queries the user if timestamps should be enabled for AR messages.

ClearInterrupt_AR

Clears the interrupt status after optionally prompting the user.

Data Structures and Constants

  • ArConfig: Configuration structure for AR settings (card index, module, channel, etc.).

  • InterruptConfig: Structure holding interrupt configuration parameters.

  • bool_t, int32_t, uint32_t, uint16_t, int8_t: Type definitions for boolean, integer, and character types.

  • Constants such as NAI_AR_MAX_DATA_LEN, NAI_GEN5_AR_MAX_CHANNEL_COUNT, NAI_AR_INTERRUPT_VECTOR, NAI_AR_STATUS_LATCHED.

Conclusion

The provided code is an example application for handling AR interrupts using NAI function modules. It involves configuring the AR module, setting up and handling interrupts, and processing the received data. Through user prompts, the code allows for dynamic configuration and status checking, providing a comprehensive example of using NAI’s SDK to interact with their hardware.

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

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "naibrd_ether.h"
#include "functions/naibrd_ar.h"
#include "maps/nai_map_ar.h"

#include <stdlib.h>

/***********************/
/* Function Prototypes */
/***********************/
void promptUserToClearInterrupt_AR();

/**************************************************************************************************************/
/**
<summary>
Prompts user to check if an interrupt has occurred. MyIsr() should be installed if using this function.
</summary>
*/
/**************************************************************************************************************/
bool_t checkForARInterrupt( ArConfig inputARConfig )
{
   bool_t bQuit;
   int32_t cardIndex;
   int32_t module;
   int32_t channel;
   nai_ar_status_t status;
   int32_t count;
   int32_t i;
   uint32_t fifoLength;
   int32_t maxFifoLength;
   uint16_t msgStatus;
   uint32_t msgData;
   uint32_t msgTStamp;
   uint32_t statArr[NAI_AR_MAX_DATA_LEN];
   uint32_t dataArr[NAI_AR_MAX_DATA_LEN];
   uint32_t tstampArr[NAI_AR_MAX_DATA_LEN];
   int32_t outnummsgs;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   cardIndex = inputARConfig.cardIndex;
   module = inputARConfig.module;
   channel = inputARConfig.channel;
   status = 0;
   bQuit = FALSE;
   interruptOccured = FALSE;
   while (!bQuit)
   {
      printf( "\nPress enter to check if interrupt Occurred (press Q to quit):" );
      bQuit = naiapp_query_ForQuitResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt );
      if (!bQuit)
      {
         if (interruptOccured)
         {
            naibrd_Wait( 1000000 );
            check_status( naibrd_AR_GetStatus( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, NAI_AR_STATUS_LATCHED, &status ) );
            check_status( naibrd_AR_GetRxBufferCnt( cardIndex, module, channel, &count ) );
            check_status( naibrd_AR_ReadFifo( cardIndex, module, channel, inputARConfig.timeStampEnable, count, statArr, dataArr, tstampArr, &outnummsgs ) );
            printf( "\nVector = %#x \n", interruptVector );
            printf( "Status = %#x \n\n", status );
            maxFifoLength = NAI_AR_MAX_DATA_LEN;
            fifoLength = count;
            printf( "Max FIFO Word Count: %d\n", maxFifoLength );
            printf( "Messages Received (FIFO Word Count): %d\n", fifoLength );
            if ( count == 1 )
            {
               msgStatus = (uint16_t)statArr[0];
               msgData = dataArr[0];
               msgTStamp = tstampArr[0];
               printf( "\n" );
               printf( "Message Status: %#x", msgStatus );
               printf( "\n" );
               printf( "Message Data: %#x", msgData );
               printf( "\n" );
               printf( "Time Stamp: %#x", msgTStamp );
               printf( "\n\n" );
            }
            else if ( count > 1 )
            {
               for ( i = 0; i < count; i++ )
               {
                  printf( "\nMessage Number %d:", i + 1 );
                  msgStatus = (uint16_t)statArr[i];
                  msgData = dataArr[i];
                  msgTStamp = tstampArr[i];
                  printf( "\n" );
                  printf( "Message Status: %#x", msgStatus );
                  printf( "\n" );
                  printf( "Message Data: %#x", msgData );
                  printf( "\n" );
                  printf( "Time Stamp: %#x", msgTStamp );
                  printf( "\n\n" );
               }
            }
            else if ( count < 1 )
            {
               printf( "ERROR! naibrd_AR_GetRxBufferCnt returned an invalid value." );
            }
            interruptOccured = FALSE;
         }
         else
         {
            printf( "\nNo Interrupt Occurred" );
         }
         printf( "\n\nWould you like to clear the status register? (default:Y):" );

         bQuit = naiapp_query_ForQuitResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt );
         if ( inputBuffer[0] == 'y' || inputBuffer[0] =='Y' || inputResponseCnt == 0 )
         {
            check_status( naibrd_AR_ClearStatus( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, 0xFFFF ) );
         }
      }
   }
   return bQuit;
}

/**************************************************************************************************************/
/**
<summary>
This function configures an interrupt to occur when a message is received on the AR channel specified by the
user.
</summary>
*/
/**************************************************************************************************************/
void configureARToInterruptOnRx( InterruptConfig inputInterruptConfig, ArConfig inputARConfig )
{
   int32_t cardIndex = inputARConfig.cardIndex;
   int32_t module = inputARConfig.module;
   int32_t channel = inputARConfig.channel;
   int32_t vector = NAI_AR_INTERRUPT_VECTOR;
   int32_t interrupt_Edge_Trigger = inputInterruptConfig.interrupt_Edge_Trigger;
   int32_t steering = inputInterruptConfig.steering;

   /* clear interruptConfigs of previous channels */
   check_status( naibrd_AR_SetInterruptEnable( cardIndex, module, channel, 0 ) );
   check_status( naibrd_AR_ClearStatus( cardIndex, module, channel, 0xFFFF ) );

   check_status( naibrd_AR_SetInterruptVector( cardIndex, module, channel, vector ) );
   check_status( naibrd_AR_SetInterruptEdgeLevel( cardIndex, module, channel, interrupt_Edge_Trigger ) );  /* Edge triggered */
   check_status( naibrd_AR_SetInterruptSteering( cardIndex, module, channel, steering ) );
}

/**************************************************************************************************************/
/**
<summary>
This function configures an interrupt to occur when a message is received on any of the AR channels specified.
</summary>
*/
/**************************************************************************************************************/
void configureARToInterruptOnRxMultiChan( InterruptConfig inputInterruptConfig, ArConfig inputARConfig )
{
   int32_t idxChan;
   int32_t cardIndex = inputARConfig.cardIndex;
   int32_t module = inputARConfig.module;
   int32_t minChan = inputARConfig.minChannel;
   int32_t maxChan = inputARConfig.maxChannel;
   int32_t vector = NAI_AR_INTERRUPT_VECTOR;
   int32_t interrupt_Edge_Trigger = inputInterruptConfig.interrupt_Edge_Trigger;
   int32_t steering = inputInterruptConfig.steering;

   /* clear interruptConfigs of previous channels */
   for ( idxChan = minChan; idxChan <= maxChan; idxChan++ )
   {
      check_status( naibrd_AR_SetInterruptEnable( cardIndex, module, idxChan, 0 ) );
      check_status( naibrd_AR_ClearStatus( cardIndex, module, idxChan, 0xFFFF ) );

      check_status( naibrd_AR_SetInterruptVector( cardIndex, module, idxChan, vector ) );
      check_status( naibrd_AR_SetInterruptEdgeLevel( cardIndex, module, idxChan, interrupt_Edge_Trigger ) );  /* Edge triggered */
      check_status( naibrd_AR_SetInterruptSteering( cardIndex, module, idxChan, steering ) );
   }
}

/**************************************************************************************************************/
/**
<summary>
DisplayMessage_ARInterrupt handles displaying the messages associated with the msgId passed in.
</summary>
*/
/**************************************************************************************************************/
void DisplayMessage_ARInterrupt( int32_t msgId )
{
   switch (msgId)
   {
      case (int32_t)MSG_BANNER_AR_INT:
      {
         printf( "\n********************************************************************************" );
         printf( "\n******                        AR INTERRUPT                               ******" );
         printf( "\nAn interrupt will occur when the AR module receives a message				   " );
         printf( "\n********************************************************************************" );
      }
      break;

      case (int32_t)MSG_USER_TRIGGER_AR_INT:
      {
         printf( "\nPress \"Q\" to quit the application.\nPlease trigger AR interrupt (Recv Msg):" );
      }
      break;

      case (int32_t)MSG_USER_CLEAR_AR_INT:
      {
         printf( "Press \"C\" to clear interrupts... " );
      }
      break;
   }
}

/**************************************************************************************************************/
/**
<summary>
Enables the channels within the (minChannel, maxChannel) range to interrupt
if enable is true and disables them otherwise.
</summary>
*/
/**************************************************************************************************************/
void enableARInterrupts( ArConfig inputARConfig, bool_t enable )
{
   int32_t channel = inputARConfig.channel;
   int32_t idxChan;

   if ( channel == 0 )
   {
      for ( idxChan = 1; idxChan <= inputARConfig.maxChannel; idxChan++ )
      {
         check_status( naibrd_AR_SetInterruptEnable( inputARConfig.cardIndex, inputARConfig.module, idxChan, enable ) );
      }
   }
   else
   {
      check_status( naibrd_AR_SetInterruptEnable( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, enable ) );
   }
}

/**************************************************************************************************************/
/**
<summary>
GetARLatchStatusTriggerMode handles prompting the user for the trigger mode for the latched status register
(Edge Triggered or Level Triggered).
</summary>
*/
/**************************************************************************************************************/
bool_t GetARLatchStatusTriggerMode( 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=1): " );
   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 = 1;
   }
   return( bQuit );
}

/**************************************************************************************************************/
/**
<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_AR( uint32_t param )
#else
void basic_ISR_AR( void *param, uint32_t vector )
#endif
{
   interruptOccured = TRUE;

#if defined (WIN32)
   UNREFERENCED_PARAMETER( param );
#endif

   #if defined (__VXWORKS__)
      interruptVector = nai_Onboard_GetInterruptVector();
      nai_Onboard_ClearInterrupt();
   #else
      interruptVector = vector;
   #endif
}

/**************************************************************************************************************/
/**
<summary>
This routine takes in the vector of the AR 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 handleARInterrupt( uint32_t nVector )
{
   static uint32_t status[NAI_GEN5_AR_MAX_CHANNEL_COUNT + 1];
   static FIFO fifoArrayToPrint[NAI_GEN5_AR_MAX_CHANNEL_COUNT + 1];

   int32_t index;
   int32_t idxChan;
   int32_t minChan;
   int32_t maxChan;
   int32_t outnummsgs;
   int32_t pathDeterminant;

   int32_t bufferCountsArray[NAI_GEN5_AR_MAX_CHANNEL_COUNT + 1];

   uint32_t mask = AR_RX_DATA_AVAIL;
   uint32_t statusMasked;
   uint32_t statArr[NAI_AR_MAX_DATA_LEN];
   uint32_t dataArr[NAI_AR_MAX_DATA_LEN];
   uint32_t tstampArr[NAI_AR_MAX_DATA_LEN];
   minChan = inputARConfig.minChannel;
   maxChan = inputARConfig.maxChannel;

   pathDeterminant = maxChan - minChan;

   naibrd_Wait( 1000000 );

   if ( pathDeterminant >= 0 )
   {
      for ( idxChan = minChan; idxChan <= maxChan; idxChan++ )
      {
         check_status( naibrd_AR_GetStatus( inputARConfig.cardIndex, inputARConfig.module, idxChan, NAI_AR_STATUS_LATCHED, &status[idxChan] ) );
         statusMasked = status[idxChan] & mask;
         if ( statusMasked == mask )
         {
            int32_t outcount;

            fifoArrayToPrint[idxChan].maxDataLength = NAI_AR_MAX_DATA_LEN;
            check_status( naibrd_AR_GetRxBufferCnt( inputARConfig.cardIndex, inputARConfig.module, idxChan, &outcount ) );
            check_status( naibrd_AR_ReadFifo( inputARConfig.cardIndex, inputARConfig.module, idxChan, inputARConfig.timeStampEnable, bufferCountsArray[idxChan], statArr, dataArr, tstampArr, &outnummsgs ) );
            for ( index = 0; index < outcount; index++ )
            {
               fifoArrayToPrint[idxChan].data[index].fifoData = dataArr[index];
               fifoArrayToPrint[idxChan].data[index].fifoStatus = (uint16_t)statArr[index];
               fifoArrayToPrint[idxChan].data[index].fifoTimeStamp = tstampArr[index];
            }
            fifoArrayToPrint[idxChan].length = bufferCountsArray[idxChan] = outcount;
         }
      }
   }
   else if ( pathDeterminant < 0 )
   {
      printf( "ERROR! Min Channel is greater than Max Channel" );
   }
   printf( "\nInterrupt Occurred\n" );
   if ( inputInterruptConfig.bPromptForInterruptClear == TRUE )
   {
      promptUserToClearInterrupt_AR();
   }
   for ( idxChan = minChan; idxChan <= maxChan; idxChan++ )
   {
      check_status( naibrd_AR_ClearStatus( inputARConfig.cardIndex, inputARConfig.module, idxChan, 0xFFFF ) );
   }
   printInterruptInformation_AR( nVector, status, fifoDataFile, bufferCountsArray, fifoArrayToPrint );
}

/**************************************************************************************************************/
/**
<summary>
Function will print the fifoData 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_AR( int32_t interruptID, uint32_t* statuses, FILE* stream, int32_t* counts, FIFO* fifos )
{
   uint8_t dataAvailStatus;
   int32_t interruptChannels[NAI_GEN5_AR_MAX_CHANNEL_COUNT + 1];
   uint16_t fifoElementStatus;
   uint32_t fifoElementData;
   uint32_t fifoElementTimeStamp;
   uint32_t fifoLength;
   int32_t maxFifoLength;
   int32_t i;
   int32_t j;

   for ( i = 1; i <= NAI_GEN5_AR_MAX_CHANNEL_COUNT; i++ )
   {
      dataAvailStatus = statuses[i] & AR_RX_DATA_AVAIL;
      if ( dataAvailStatus == 1 )
      {
         interruptChannels[i] = i;
      }
      else
      {
         interruptChannels[i] = 0;
      }
   }

   for ( i = 1; i <= NAI_GEN5_AR_MAX_CHANNEL_COUNT; i++ )
   {
      if ( interruptChannels[i] > 0 )
      {
         fprintf( stream, "Interrupt Information\n" );
         fprintf( stream, "-----------------------------------\n" );
         fprintf( stream, "\nInterrupt Channel = %d \n", i );
         fprintf( stream, "IDR ID = %#x \n", interruptID );
         fprintf( stream, "Status = %#x \n", statuses[i] );

         dataAvailStatus = statuses[i] & AR_RX_DATA_AVAIL;
         if (dataAvailStatus)
         {
            if ( counts[i] == 1 )
            {
               fifoElementStatus = fifos[i].data[0].fifoStatus;
               fifoElementData = fifos[i].data[0].fifoData;
               fifoElementTimeStamp = fifos[i].data[0].fifoTimeStamp;
               fprintf( stream, "\n" );
               fprintf( stream, "Message Status: %#x", fifoElementStatus );
               fprintf( stream, "\n" );
               fprintf( stream, "Message Data: %#x", fifoElementData );
               fprintf( stream, "\n" );
               fprintf( stream, "Time Stamp: %#x", fifoElementTimeStamp );
               fprintf( stream, "\n\n" );
            }
            else if ( counts[i] > 1 )
            {
               fifoLength = fifos[i].length;
               maxFifoLength = fifos[i].maxDataLength;
               fprintf( stream, "\nMax FIFO Word Count: %d\n", maxFifoLength );
               fprintf( stream, "Messages Received (FIFO Word Count): %d\n", fifoLength );
               for ( j = 0; j < counts[i]; j++ )
               {
                  fprintf( stream, "\nMessage Number %d:", j+1 );
                  fifoElementStatus = fifos[i].data[j].fifoStatus;
                  fifoElementData = fifos[i].data[j].fifoData;
                  fifoElementTimeStamp = fifos[i].data[j].fifoTimeStamp;
                  fprintf( stream, "\n" );
                  fprintf( stream, "Message Status: %#x", fifoElementStatus );
                  fprintf( stream, "\n" );
                  fprintf( stream, "Message Data: %#x", fifoElementData );
                  fprintf( stream, "\n" );
                  fprintf( stream, "Time Stamp: %#x", fifoElementTimeStamp );
                  fprintf( stream, "\n\n" );
               }
            }
            else if ( counts[i] < 1 )
            {
               fprintf( stream, "ERROR! naibrd_AR_GetRxBufferCnt returned an invalid value." );
            }
         }
         fprintf( stream, "\n-----------------------------------\n" );
      }
   }
}

void promptUserToClearInterrupt_AR()
{
   /* Prompt the user to clear the interrupt received */
   SetUserRequestClearInt( FALSE );
   printf( "\n" );
   DisplayMessage_ARInterrupt( MSG_USER_CLEAR_AR_INT );

   /* Wait for the user to respond */
   while ( !GetUserRequestClearInt() )
   {
      nai_msDelay( 10 );
   }
}

/**************************************************************************************************************/
/**
<summary>
QueryUserForTimeStampEnable handles querying the user to see if he wants time stamps to be enabled and
included in AR messages. If the user specifies 'N', time stamping will be disabled, else time stamping will
be enabled.
</summary>
*/
/**************************************************************************************************************/
bool_t QueryUserForTimeStampEnable( bool_t* tstampEnable )
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   /* Query the user to determine if he wants time stamps to be included in AR messages */
   printf( "\nWould you like to enable time stamping for messages received? (Y or N) (Default: Y): " );
   bQuit = naiapp_query_ForQuitResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt );
   if (!bQuit)
   {
      if ( inputResponseCnt != 0 )
      {
         if ( ( inputBuffer[0] == 'N' ) || ( inputBuffer[0] == 'n' ) )
         {
            *tstampEnable = FALSE;
         }
         else
         {
            *tstampEnable = TRUE;
         }
      }
      else
      {
         *tstampEnable = TRUE;
      }
   }
   return bQuit;
}

void ClearInterrupt_AR()
{
	uint32_t status;
	if (inputInterruptConfig.bPromptForInterruptClear)
	{
		promptUserToClearInterrupt_AR();
	}
   naibrd_AR_GetStatus( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, NAI_AR_STATUS_LATCHED, &status );
   naibrd_AR_ClearStatus( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, status );
}

Help Bot

X