CTS DIF SAMPLE APP
Edit this on GitLab
CTS DIF SAMPLE APP
Explanation
About This Sample Application Code
This sample application code is designed for interacting with the North Atlantic Industries (NAI) embedded function modules using their Software Support Kit (SSK). This specific application is tailored to handle and manage two DF3 modules on a 75G5 card. The code prepares these modules, loads them with event data from a CSV file, initiates them, and monitors for events. Below is a detailed explanation of how the code functions:
Code Breakdown
Including Headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.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"
#include "naibrd.h"
#include "boards/naibrd_gen5.h"
#include "functions/naibrd_dif_cts.h"
These headers include standard C libraries and NAI-specific libraries necessary for interrupt handling, board access, and specific functionalities related to NAI devices.
Defining Constants and Structs
#define _ONLY_BITS_RELEVANT_TO_MODULE_SLOT 1
static const int8_t *SAMPLE_PGM_NAME = (int8_t *)"CTS_DIF";
static const uint32_t EVENT_DETECTED = 0x00000040;
#define MAX_EVENTS 5000
struct _EventStruct
{
int32_t courseCounter;
int32_t subSecCounter;
int32_t value;
int32_t moduleSlotRawValue;
int32_t rawCompositeValue;
};
static struct _EventStruct g_firstDF3Events[MAX_EVENTS];
static struct _EventStruct g_secondDF3Events[MAX_EVENTS];
Here, constants and a structure are defined. MAX_EVENTS
limits the number of events it can handle. The _EventStruct
contains members for various event-related counters and values.
Function Prototypes
void run_DF3_SAMPLE_APP(void);
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping);
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping);
static void fill_Event_Struct(int32_t DF3ModuleSlot, char* line, struct _EventStruct *eventStruct);
void init_DF3_Module(int32_t cardIndex, int32_t DF3ModuleSlot, char const* DF3EventDataFile, struct _EventStruct *DF3Events);
nai_status_t setup_DF3_Interrupts(int32_t cardIndex, int32_t DF3ModuleSlot);
void my_DF3_Isr(void* param, uint32_t vector);
Function prototypes provide forward declarations of functions defined later in the code.
Global Variables
uint32_t g_TotalEventCount = 0;
uint32_t g_CardIndex = 0;
int32_t g_DF3_FirstSlot = 0;
int32_t g_DF3_SecondSlot = 0;
int8_t g_ActiveSlotCount = 0;
int8_t g_SilentMode = 0;
int8_t g_InitCounters = 0;
int8_t g_DF3UseMapping = 1;
char g_DF3EventDataFile[20];
Global variables needed throughout the program are declared here.
Main Function
int32_t main(int argc, const char *argv[])
{
...
// Setup default values and handle command-line arguments
...
run_DF3_SAMPLE_APP();
...
return 0;
}
The main function initializes values, processes command-line arguments, then calls run_DF3_SAMPLE_APP()
to start the main functionality.
Event Mapping Functions
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping)
{
...
// Mapping logic based on the module slot and whether mapping is used
...
return nMappedEventValue;
}
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping)
{
...
// Reverse mapping logic based on the module slot and whether mapping is used
...
return nReversedMappedEventValue;
}
These functions convert event values to their corresponding mapped values based on the DF3 module slot.
Filling Event Struct
static void fill_Event_Struct(int32_t DF3ModuleSlot, char* line, struct _EventStruct *eventStruct)
{
...
// Parse line and populate the event struct fields
...
}
Parses a line from the CSV file and fills in an event struct accordingly.
Initializing DF3 Module
void init_DF3_Module(int32_t cardIndex, int32_t DF3ModuleSlot, char const* DF3EventDataFile, struct _EventStruct *DF3Events)
{
...
// Initialization steps to configure the DF3 module and load event data
// Open the data file, read event data, fill structs, and initialize the DF3 module
...
}
This function initializes the hardware pins, counters, and loads specified event data from a CSV file for the given DF3 module.
Running the Sample App
void run_DF3_SAMPLE_APP()
{
...
// Setup DF3 modules and monitor them for events
// This involves checking event statuses and comparing expected values
...
}
The application runs by opening the card, setting up interrupts, initializing DF3 modules, and then monitoring them for events, printing relevant details.
Setting Up Interrupts
nai_status_t setup_DF3_Interrupts(int32_t cardIndex, int32_t DF3ModuleSlot)
{
...
// Configures and registers ISR for handling DF3 interrupts
// Set Edge Driven interrupts and configure interrupt steering
...
return status;
}
This function sets up interrupts to handle module events and synchronizes counters.
Interrupt Service Routine
void my_DF3_Isr(void* param, uint32_t vector)
{
...
// ISR to initialize/synchronize counters or handle interrupt signals.
// Clears the interrupt once handled.
...
}
The ISR synchronizes the DF3 module counters and clears any handled interrupts.
Usage - Define the CSV file containing event data. - Compile and execute the program. - Monitor terminal output for event handling and status reports.
This sample code is a structured illustration of handling embedded function modules using NAI’s SSK, providing a configurable and extendable framework for various specific applications.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Common Sample Program include files */
#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 "naibrd.h"
#include "boards/naibrd_gen5.h"
#include "functions/naibrd_dif_cts.h"
#define _ONLY_BITS_RELEVANT_TO_MODULE_SLOT 1
static const int8_t *SAMPLE_PGM_NAME = (int8_t *)"CTS_DIF";
static const uint32_t EVENT_DETECTED = 0x00000040;
#define MAX_EVENTS 5000
struct _EventStruct
{
int32_t courseCounter;
int32_t subSecCounter;
int32_t value;
int32_t moduleSlotRawValue;
int32_t rawCompositeValue;
};
static struct _EventStruct g_firstDF3Events[MAX_EVENTS];
static struct _EventStruct g_secondDF3Events[MAX_EVENTS];
/* Function prototypes */
void run_DF3_SAMPLE_APP(void);
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping);
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping);
static void fill_Event_Struct(int32_t DF3ModuleSlot, char* line, struct _EventStruct *eventStruct);
void init_DF3_Module(int32_t cardIndex, int32_t DF3ModuleSlot, char const* DF3EventDataFile, struct _EventStruct *DF3Events);
nai_status_t setup_DF3_Interrupts(int32_t cardIndex, int32_t DF3ModuleSlot);
void my_DF3_Isr(void* param, uint32_t vector);
/* Global Variables */
uint32_t g_TotalEventCount = 0;
uint32_t g_CardIndex = 0;
int32_t g_DF3_FirstSlot = 0;
int32_t g_DF3_SecondSlot = 0;
int8_t g_ActiveSlotCount = 0;
int8_t g_SilentMode = 0;
int8_t g_InitCounters = 0;
int8_t g_DF3UseMapping = 1;
char g_DF3EventDataFile[20];
/**************************************************************************************************************/
/**
<summary>
DF3_SAMPLE_APP opens the 75G5 card at card index 0; initializes two DF3 modules by forcing all pins to be
output, setting the course and subsec counters to a default value, and loading each DF3 module with specific
event information of what values to output when specified times (counter values) are reached. The event
information for each DF3 module is read from a dedicated CSV file for that particular module. NOTE: The filenames
used for the event information must match what the following code is expecting.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DIF_CTS_Sample(int argc, const char *argv[])
#else
int32_t main(int argc, const char *argv[])
#endif
{
int i = 0;
printf("\n");
printf("NAI Sample Program: %s\n", SAMPLE_PGM_NAME);
printf("=============================================================================\n\n");
sprintf(g_DF3EventDataFile, "%s", "eventdata.txt");
#if defined (_DEBUG_PRINT)
printf("Argc = %d\n", argc);
for (i=0; i < argc; i++)
printf("Arg %d = %s\n", i, argv[i]);
#endif
if (argc == 1)
{
/*By Default DF3 is found in slots 2 and 3 */
g_DF3_FirstSlot = 2;
g_DF3_SecondSlot = 3;
g_ActiveSlotCount = 2;
}
else
{
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-s") == 0)
g_SilentMode = 1;
else if (strcmp(argv[i], "-d") == 0) /* -d = "Direct" i.e. do not use mapping! */
g_DF3UseMapping = 0;
else if (strcmp(argv[i], "-f") == 0) /* -f = "File i.e. what event file to use! */
{
i++;
sprintf(g_DF3EventDataFile, "%s", argv[i]);
}
else if (g_DF3_FirstSlot == 0)
{
g_DF3_FirstSlot = atoi(argv[i]);
g_ActiveSlotCount++;
}
else if (g_DF3_SecondSlot == 0)
{
g_DF3_SecondSlot = atoi(argv[i]);
g_ActiveSlotCount++;
}
}
}
/* If both slots are still zero - caller did not specify slots so by default we assume both are available */
if (g_DF3_FirstSlot == 0 && g_DF3_SecondSlot == 0)
{
g_DF3_FirstSlot = 2;
g_DF3_SecondSlot = 3;
g_ActiveSlotCount = 2;
}
if (g_SilentMode)
printf("Silent Mode Detected - Event tables will be loaded but this application will not attempt to detect event status.\n");
run_DF3_SAMPLE_APP();
printf("Exiting DF3_SAMPLE_APP!\n");
return 0;
}
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping)
{
int32_t nMappedEventValue = 0;
if (DF3UseMapping)
{
if (DF3ModuleSlot == 2)
{
if (nEventValue & 0x00001) /* BIT 0 ==> Channel 1 (BIT 0) */
nMappedEventValue |= 0x00001;
if (nEventValue & 0x00002) /* BIT 1 ==> Channel 2 (BIT 1) */
nMappedEventValue |= 0x00002;
if (nEventValue & 0x00004) /* BIT 2 ==> Channel 4 (BIT 3) */
nMappedEventValue |= 0x00008;
if (nEventValue & 0x00008) /* BIT 3 ==> Channel 5 (BIT 4) */
nMappedEventValue |= 0x00010;
if (nEventValue & 0x00010) /* BIT 4 ==> Channel 6 (BIT 5) */
nMappedEventValue |= 0x00020;
if (nEventValue & 0x00020) /* BIT 5 ==> Channel 8 (BIT 7) */
nMappedEventValue |= 0x00080;
if (nEventValue & 0x00040) /* BIT 6 ==> Channel 9 (BIT 8) */
nMappedEventValue |= 0x00100;
if (nEventValue & 0x00080) /* BIT 7 ==> Channel 14 (BIT 13) */
nMappedEventValue |= 0x02000;
if (nEventValue & 0x80000) /* BIT 19 ==> Channel 12 (BIT 11) */
nMappedEventValue |= 0x00800;
}
else if (DF3ModuleSlot == 3)
{
if (nEventValue & 0x00100) /* BIT 8 ==> Channel 1 (BIT 0) */
nMappedEventValue |= 0x00001;
if (nEventValue & 0x00200) /* BIT 9 ==> Channel 2 (BIT 1) */
nMappedEventValue |= 0x00002;
if (nEventValue & 0x00400) /* BIT 10 ==> Channel 4 (BIT 3) */
nMappedEventValue |= 0x00008;
if (nEventValue & 0x00800) /* BIT 11 ==> Channel 6 (BIT 5) */
nMappedEventValue |= 0x00020;
if (nEventValue & 0x01000) /* BIT 12 ==> Channel 8 (BIT 7) */
nMappedEventValue |= 0x00080;
if (nEventValue & 0x02000) /* BIT 13 ==> Channel 10 (BIT 9) */
nMappedEventValue |= 0x00400;
if (nEventValue & 0x04000) /* BIT 14 ==> Channel 13 (BIT 12) */
nMappedEventValue |= 0x01000;
if (nEventValue & 0x08000) /* BIT 15 ==> Channel 9 (BIT 8) */
nMappedEventValue |= 0x00100;
if (nEventValue & 0x10000) /* BIT 16 ==> Channel 12 (BIT 11) */
nMappedEventValue |= 0x00800;
if (nEventValue & 0x20000) /* BIT 17 ==> Channel 14 (BIT 13) */
nMappedEventValue |= 0x02000;
if (nEventValue & 0x40000) /* BIT 18 ==> Channel 16 (BIT 15) */
nMappedEventValue |= 0x08000;
}
}
else /* Direct! */
{
#if defined (_ONLY_BITS_RELEVANT_TO_MODULE_SLOT)
if (DF3ModuleSlot == 2)
{
if (nEventValue & 0x00001)
nMappedEventValue |= 0x00001;
if (nEventValue & 0x00002)
nMappedEventValue |= 0x00002;
if (nEventValue & 0x00004)
nMappedEventValue |= 0x00004;
if (nEventValue & 0x00008)
nMappedEventValue |= 0x00008;
if (nEventValue & 0x00010)
nMappedEventValue |= 0x00010;
if (nEventValue & 0x00020)
nMappedEventValue |= 0x00020;
if (nEventValue & 0x00040)
nMappedEventValue |= 0x00040;
if (nEventValue & 0x00080)
nMappedEventValue |= 0x00080;
if (nEventValue & 0x80000)
nMappedEventValue |= 0x80000;
}
else if (DF3ModuleSlot == 3)
{
if (nEventValue & 0x00100)
nMappedEventValue |= 0x00100;
if (nEventValue & 0x00200)
nMappedEventValue |= 0x00200;
if (nEventValue & 0x00400)
nMappedEventValue |= 0x00400;
if (nEventValue & 0x00800)
nMappedEventValue |= 0x00800;
if (nEventValue & 0x01000)
nMappedEventValue |= 0x01000;
if (nEventValue & 0x02000)
nMappedEventValue |= 0x02000;
if (nEventValue & 0x04000)
nMappedEventValue |= 0x04000;
if (nEventValue & 0x08000)
nMappedEventValue |= 0x08000;
if (nEventValue & 0x10000)
nMappedEventValue |= 0x10000;
if (nEventValue & 0x20000)
nMappedEventValue |= 0x20000;
if (nEventValue & 0x40000)
nMappedEventValue |= 0x40000;
}
#else
nMappedEventValue = nEventValue;
#endif
}
return nMappedEventValue;
}
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue, int8_t DF3UseMapping)
{
int32_t nReversedMappedEventValue = 0;
if (DF3UseMapping)
{
if (DF3ModuleSlot == 2)
{
if (nEventValue & 0x00001) /* BIT 0 (Channel 1) ==> BIT 0 */
nReversedMappedEventValue |= 0x00001;
if (nEventValue & 0x00002) /* BIT 1 (Channel 2) ==> BIT 1 */
nReversedMappedEventValue |= 0x00002;
if (nEventValue & 0x00008) /* BIT 3 (Channel 4) ==> BIT 2 */
nReversedMappedEventValue |= 0x00004;
if (nEventValue & 0x00010) /* BIT 4 (Channel 5) ==> BIT 3 */
nReversedMappedEventValue |= 0x00008;
if (nEventValue & 0x00020) /* BIT 5 (Channel 6) ==> BIT 4 */
nReversedMappedEventValue |= 0x00010;
if (nEventValue & 0x00080) /* BIT 7 (Channel 8) ==> BIT 5 */
nReversedMappedEventValue |= 0x00020;
if (nEventValue & 0x00100) /* BIT 8 (Channel 9) ==> BIT 6 */
nReversedMappedEventValue |= 0x00040;
if (nEventValue & 0x02000) /* BIT 13 (Channel 14) ==> BIT 7 */
nReversedMappedEventValue |= 0x00080;
if (nEventValue & 0x00800) /* BIT 11 (Channel 12) ==> BIT 19 */
nReversedMappedEventValue |= 0x80000;
}
else if (DF3ModuleSlot == 3)
{
if (nEventValue & 0x00001) /* BIT 0 (Channel 1) ==> BIT 8 */
nReversedMappedEventValue |= 0x00100;
if (nEventValue & 0x00002) /* BIT 1 (Channel 2) ==> BIT 9 */
nReversedMappedEventValue |= 0x00200;
if (nEventValue & 0x00008) /* BIT 3 (Channel 4) ==> BIT 10 */
nReversedMappedEventValue |= 0x00400;
if (nEventValue & 0x00020) /* BIT 5 (Channel 6) ==> BIT 11 */
nReversedMappedEventValue |= 0x00800;
if (nEventValue & 0x00080) /* BIT 7 (Channel 8) ==> BIT 12 */
nReversedMappedEventValue |= 0x01000;
if (nEventValue & 0x00400) /* BIT 9 (Channel 10) ==> BIT 13 */
nReversedMappedEventValue |= 0x02000;
if (nEventValue & 0x01000) /* BIT 12 (Channel 13) ==> BIT 14 */
nReversedMappedEventValue |= 0x04000;
if (nEventValue & 0x00100) /* BIT 8 (Channel 9) ==> BIT 15 */
nReversedMappedEventValue |= 0x08000;
if (nEventValue & 0x00800) /* BIT 11 (Channel 12) ==> BIT 16 */
nReversedMappedEventValue |= 0x10000;
if (nEventValue & 0x02000) /* BIT 13 (Channel 14) ==> BIT 17 */
nReversedMappedEventValue |= 0x20000;
if (nEventValue & 0x08000) /* BIT 15 (Channel 16) ==> BIT 18 */
nReversedMappedEventValue |= 0x40000;
}
}
else /* Direct */
{
#if defined (_ONLY_BITS_RELEVANT_TO_MODULE_SLOT)
if (DF3ModuleSlot == 2)
{
if (nEventValue & 0x00001)
nReversedMappedEventValue |= 0x00001;
if (nEventValue & 0x00002)
nReversedMappedEventValue |= 0x00002;
if (nEventValue & 0x00004)
nReversedMappedEventValue |= 0x00004;
if (nEventValue & 0x00008)
nReversedMappedEventValue |= 0x00008;
if (nEventValue & 0x00010)
nReversedMappedEventValue |= 0x00010;
if (nEventValue & 0x00020)
nReversedMappedEventValue |= 0x00020;
if (nEventValue & 0x00040)
nReversedMappedEventValue |= 0x00040;
if (nEventValue & 0x00080)
nReversedMappedEventValue |= 0x00080;
if (nEventValue & 0x80000)
nReversedMappedEventValue |= 0x80000;
}
else if (DF3ModuleSlot == 3)
{
if (nEventValue & 0x00100)
nReversedMappedEventValue |= 0x00100;
if (nEventValue & 0x00200)
nReversedMappedEventValue |= 0x00200;
if (nEventValue & 0x00400)
nReversedMappedEventValue |= 0x00400;
if (nEventValue & 0x00800)
nReversedMappedEventValue |= 0x00800;
if (nEventValue & 0x01000)
nReversedMappedEventValue |= 0x01000;
if (nEventValue & 0x02000)
nReversedMappedEventValue |= 0x02000;
if (nEventValue & 0x04000)
nReversedMappedEventValue |= 0x04000;
if (nEventValue & 0x08000)
nReversedMappedEventValue |= 0x08000;
if (nEventValue & 0x10000)
nReversedMappedEventValue |= 0x10000;
if (nEventValue & 0x20000)
nReversedMappedEventValue |= 0x20000;
if (nEventValue & 0x40000)
nReversedMappedEventValue |= 0x40000;
}
#else
nReversedMappedEventValue = nEventValue;
#endif
}
return nReversedMappedEventValue;
}
/**************************************************************************************************************/
/**
<summary>
fill_Event_Struct is responsible for parsing a single line from the event information CSV file and populating
associated fields in the _EventStruct passed in. It is expected that each line will have 3 HEX values
separated by a comma ",".
</summary>
*/
/**************************************************************************************************************/
static void fill_Event_Struct(int32_t DF3ModuleSlot, char* line, struct _EventStruct *eventStruct)
{
const char* tok;
int32_t nEventValue = 0;
tok = strtok(line, ",\n");
if (tok != NULL)
{
eventStruct->courseCounter = (int32_t)strtol(tok, NULL, 0);
tok = strtok(NULL, ",\n");
if (tok != NULL)
{
eventStruct->subSecCounter = (int32_t)strtol(tok, NULL, 0);
tok = strtok(NULL, ",\n");
if (tok != NULL)
{
nEventValue = (int32_t)strtol(tok, NULL, 0);
eventStruct->value = map_DF3_EventValue(DF3ModuleSlot, nEventValue, g_DF3UseMapping);
eventStruct->moduleSlotRawValue = map_DF3_EventValue(DF3ModuleSlot, nEventValue, 0 /* Store specific module slot representation of the event data. */);
eventStruct->rawCompositeValue = nEventValue; /* Store the full event value - this value gets split between module slot 1 and module slot 2..but having the full value at our fingertips is helpful */
}
}
}
}
/**************************************************************************************************************/
/**
<summary>
init_DF3_Module is responsible for initializing a specific DF3 module by forcing all pins to be
output, setting the course and subsec counters to a default value, and loading the DF3 module with specific
event information of what values to output when specified times (counter values) are reached. The event
information for the DF3 module is read from a dedicated CSV file.
</summary>
*/
/**************************************************************************************************************/
void init_DF3_Module(int32_t cardIndex, int32_t DF3ModuleSlot, char const* DF3EventDataFile, struct _EventStruct *DF3Events)
{
FILE* file = NULL;
char line[256];
int32_t count = 0;
/* Set all pins as output */
naibrd_WriteReg32(cardIndex, DF3ModuleSlot, 0x00001038, 0x0000ffff);
/* Tell the module what slot it is in */
naibrd_WriteReg32(cardIndex, DF3ModuleSlot, 0x00001108, DF3ModuleSlot);
/* Flush all Queues */
/* naibrd_WriteReg32(cardIndex, DF3ModuleSlot, 0x00001104, 0x00000000); */
naibrd_DIF_CTS_FlushQueues(cardIndex, DF3ModuleSlot);
/* Open the event file */
file = fopen(DF3EventDataFile, "r");
printf("*****************************************************************************\n");
printf("DF3 Module Slot %d Event Data\n", DF3ModuleSlot);
printf("*****************************************************************************\n");
/* Initialize with events */
while (fgets(line, sizeof(line), file))
{
count++;
if (count < MAX_EVENTS)
{
fill_Event_Struct(DF3ModuleSlot, line, &DF3Events[count-1]);
/* note that fgets does not strip the terminating \n, checking its presence would allow to handle lines longer that sizeof(line) */
printf("%d - Course = 0x%08x SubSec = 0x%08x Value = 0x%08x\n", count, DF3Events[count-1].courseCounter, DF3Events[count-1].subSecCounter, DF3Events[count-1].value);
/* Load the Event Table */
naibrd_DIF_CTS_WriteEvent(cardIndex, DF3ModuleSlot, DF3Events[count-1].courseCounter, DF3Events[count-1].subSecCounter, DF3Events[count-1].value);
g_TotalEventCount++;
}
else
{
printf("*******************************************************************************************\n");
printf("Event Count exceeded %d - the maximum number of events expected for this trivial sample app!\n", MAX_EVENTS);
printf("*******************************************************************************************\n");
break;
}
}
printf("\n");
fclose(file);
}
/**************************************************************************************************************/
/**
<summary>
run_DF3_SAMPLE_APP is responsible for opening up the specified 75G5 card; initializing the desired DF3 modules
and then monitoring and outputting each of the DF3 modules' "ReadIO" register whenever an event is reached.
</summary>
*/
/**************************************************************************************************************/
void run_DF3_SAMPLE_APP()
{
nai_status_t status;
uint32_t detectedEventCount = 0;
uint32_t firstDF3DetectedEventCount = 0;
uint32_t secondDF3DetectedEventCount = 0;
uint32_t firstDF3ModuleSlotStatus = 0;
int32_t firstDF3ModuleSlot = g_DF3_FirstSlot;
uint32_t firstDF3ReadBackValue = 0;
int32_t secondDF3ModuleSlot = g_DF3_SecondSlot;
uint32_t secondDF3ReadBackValue = 0;
uint32_t DF3CourseCounter = 0;
uint32_t DF3ExpectedCourseCounter = 0;
uint32_t DF3SubSecCounter = 0;
uint32_t DF3ExpectedSubSecCounter = 0;
uint32_t DF3ExpectedRawCompositeEventValue = 0;
uint32_t DF3CompositeReadBackValue = 0;
status = check_status(naibrd_OpenDevice(g_CardIndex, NAIBRD_COMM_ONBOARD, NAI_DEV_NAME_75G5));
if (status != NAI_SUCCESS)
{
return;
}
/* Make sure we start with cleared interrupt register */
/* naibrd_WriteReg32(g_CardIndex, firstDF3ModuleSlot, 0x0844, 0xFFFF); */
naibrd_DIF_ClearGroupStatusRaw(g_CardIndex, firstDF3ModuleSlot, 1, NAI_DIF_CTS_STATUS_RUN_LATCHED, 0xFFFF);
/* Setup to receive the 1 second interrupt from the 1st DF3 module slot - NOTE: we only have
* to register for 1 DF3 (doesn't matter which) - we do this so we can synchronize the counters */
status = setup_DF3_Interrupts(g_CardIndex, firstDF3ModuleSlot);
if (status != NAI_SUCCESS)
{
printf("Problem setting up DF3 interrupts for card: %d module %d\n", g_CardIndex, firstDF3ModuleSlot);
printf("Status = %d\n", status);
return;
}
/* Now signal it is ok to re-initialize the counters to the desired starting point now that
* event data is loaded. */
g_InitCounters = 1;
/* Now wait until counters have been initialized */
while (g_InitCounters == 1)
;
/* Now initialize each active D3 module with desired event data */
if (firstDF3ModuleSlot != 0)
init_DF3_Module(g_CardIndex, firstDF3ModuleSlot, g_DF3EventDataFile, g_firstDF3Events);
if (secondDF3ModuleSlot != 0)
init_DF3_Module(g_CardIndex, secondDF3ModuleSlot, g_DF3EventDataFile, g_secondDF3Events);
/* Halve the total event count since we load both DF3 modules with same event data they should only be counted once */
g_TotalEventCount /= 2;
/* Now signal it is ok to re-initialize the counters to the desired starting point now that
* event data is loaded. */
g_InitCounters = 2;
/* Now wait until counters have been initialized */
while (g_InitCounters == 2)
;
/* Now disable the CTS PULSE interrupt since we have already synchronized the clocks and we no longer need to be interrupted */
check_status(naibrd_DIF_CTS_SetInterruptEnable(g_CardIndex, firstDF3ModuleSlot, NAI_DIF_CTS_INT_EXT_PULSE, 0));
/* For Silent Mode - we just initialize the DF3 Module(s) and then exit */
if (!g_SilentMode)
{
printf("=============================================================================\n");
printf("Waiting for %u events...\n", g_TotalEventCount);
while (1)
{
DF3CompositeReadBackValue = 0;
DF3ExpectedRawCompositeEventValue = 0;
DF3ExpectedCourseCounter = 0;
DF3ExpectedSubSecCounter = 0;
if (firstDF3ModuleSlot != 0)
{
/* See if 1st DF3 module has had event triggered */
/* Read the latched status register to see if an event has been fired for the first DF3 slot */
naibrd_ReadReg32(g_CardIndex, firstDF3ModuleSlot, 0x00000844, &firstDF3ModuleSlotStatus);
if ((firstDF3ModuleSlotStatus & EVENT_DETECTED) == EVENT_DETECTED)
{
/* Clear the latch */
naibrd_WriteReg32(g_CardIndex, firstDF3ModuleSlot, 0x00000844, EVENT_DETECTED);
/* naibrd_ReadReg32(g_CardIndex, firstDF3ModuleSlot, 0x00001000, &firstDF3TempReadBackValue); */
naibrd_DIF_GetGroupInputStateRaw(g_CardIndex, firstDF3ModuleSlot, 1, &firstDF3ReadBackValue);
firstDF3ReadBackValue = reverseMap_DF3_EventValue(firstDF3ModuleSlot, firstDF3ReadBackValue, g_DF3UseMapping);
naibrd_DIF_CTS_GetCourseCounter(g_CardIndex, firstDF3ModuleSlot, &DF3CourseCounter);
naibrd_DIF_CTS_GetSubsecCounter(g_CardIndex, firstDF3ModuleSlot, &DF3SubSecCounter);
DF3CompositeReadBackValue |= firstDF3ReadBackValue;
DF3ExpectedCourseCounter = g_firstDF3Events[firstDF3DetectedEventCount].courseCounter;
DF3ExpectedSubSecCounter = g_firstDF3Events[firstDF3DetectedEventCount].subSecCounter;
DF3ExpectedRawCompositeEventValue = g_firstDF3Events[firstDF3DetectedEventCount].rawCompositeValue;
firstDF3DetectedEventCount++;
/* Take the detected event count of the 1st DF3 (since if 2 modules exist they should be the same if we got here) */
detectedEventCount = firstDF3DetectedEventCount;
if (secondDF3ModuleSlot != 0)
{
/* naibrd_ReadReg32(g_CardIndex, secondDF3ModuleSlot, 0x00001000, &secondDF3TempReadBackValue); */
naibrd_DIF_GetGroupInputStateRaw(g_CardIndex, secondDF3ModuleSlot, 1, &secondDF3ReadBackValue);
secondDF3ReadBackValue = reverseMap_DF3_EventValue(secondDF3ModuleSlot, secondDF3ReadBackValue, g_DF3UseMapping);
naibrd_DIF_CTS_GetCourseCounter(g_CardIndex, secondDF3ModuleSlot, &DF3CourseCounter);
naibrd_DIF_CTS_GetSubsecCounter(g_CardIndex, secondDF3ModuleSlot, &DF3SubSecCounter);
DF3CompositeReadBackValue |= secondDF3ReadBackValue;
DF3ExpectedCourseCounter = g_secondDF3Events[secondDF3DetectedEventCount].courseCounter;
DF3ExpectedSubSecCounter = g_secondDF3Events[secondDF3DetectedEventCount].subSecCounter;
secondDF3DetectedEventCount++;
}
/* If both DF3 slots are in use...they better have the same detected number of events! */
if (firstDF3ModuleSlot != 0 && secondDF3ModuleSlot != 0)
{
if (firstDF3DetectedEventCount != secondDF3DetectedEventCount)
{
printf("\n!!!!!!!!!!FAILURE!!!!!!!!!!!FAILURE!!!!!!!!!!!!!!FAILURE!!!!!!!!!!FAILURE!!!!!!!!!!!!!!!!FAILURE!!!!!!!!!!!\n");
printf("Different Number of Detected Events! First DF3 Event Count = %u Second DF3 Event Count = %u\n", firstDF3DetectedEventCount, secondDF3DetectedEventCount);
printf("!!!!!!!!!!FAILURE!!!!!!!!!!!FAILURE!!!!!!!!!!!!!!FAILURE!!!!!!!!!!FAILURE!!!!!!!!!!!!!!!!FAILURE!!!!!!!!!!!\n");
break;
}
}
/* Check to see if the course counter we just read equals the expected course counter of the event that was detected..it should since we should detect the event well within 1 second */
if (DF3CourseCounter != DF3ExpectedCourseCounter ||
DF3CompositeReadBackValue != DF3ExpectedRawCompositeEventValue)
{
printf("\n!!!!!!!!!!FAILURE!!!!!!!!!!!FAILURE!!!!!!!!!!!!!!FAILURE!!!!!!!!!!FAILURE!!!!!!!!!!!!!!!!FAILURE!!!!!!!!!!!\n");
printf("%u : DF3 Module Event Detected\n", detectedEventCount);
printf("Expected Value : 0x%08x Actual Value : 0x%08x\n",DF3ExpectedRawCompositeEventValue, DF3CompositeReadBackValue);
printf("Expected Course Counter: 0x%08x Actual Course Counter: 0x%08x\n",DF3ExpectedCourseCounter, DF3CourseCounter);
printf("Expected SubSec Counter: 0x%08x Actual SubSec Counter: 0x%08x\n",DF3ExpectedSubSecCounter, DF3SubSecCounter);
printf("!!!!!!!!!!FAILURE!!!!!!!!!!!FAILURE!!!!!!!!!!!!!!FAILURE!!!!!!!!!!FAILURE!!!!!!!!!!!!!!!!FAILURE!!!!!!!!!!!\n\n");
}
else
{
printf("%u : DF3 Module Event Detected - Value = 0x%08x\n", detectedEventCount, DF3CompositeReadBackValue);
printf("Expected Course Counter: 0x%08x Actual Course Counter: 0x%08x\n", DF3ExpectedCourseCounter, DF3CourseCounter);
printf("Expected SubSec Counter: 0x%08x Actual SubSec Counter: 0x%08x\n\n", DF3ExpectedSubSecCounter, DF3SubSecCounter);
}
if (detectedEventCount >= g_TotalEventCount)
{
printf("All scheduled events have been fired\n");
break;
}
} /* END Event Detected */
} /* END firstDF3ModuleSlot != 0 */
} /* END While(1) */
} /* END !g_SilentMode */
/* Close the card */
check_status(naibrd_Close(g_CardIndex));
}
/******************************/
/* Interrupt Service Routines */
/******************************/
/**************************************************************************************************************/
/**
<summary>
setup_DF3_Interrupts is responsible for setting up the Run Status interrupt that will be handled from a specified
DF3 module. A callback function, my_DF3_Isr is registered and the appropriate IRQ and steering are configured to
force the callback to be called once per second. (Enabled to receive interrupts for just "CTS 1PPS Pulse" - bit 8
of Run Status register.
</summary>
*/
/**************************************************************************************************************/
nai_status_t setup_DF3_Interrupts(int32_t cardIndex, int32_t DF3ModuleSlot)
{
int chan = 1;
nai_status_t status;
status = check_status(naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_ON_BOARD_0, (nai_isr_t)my_DF3_Isr, NULL));
/* Set Edge Driven Interrupt (as opposed to Level) */
if (status == NAI_SUCCESS)
/* status = check_status(naibrd_WriteReg32(cardIndex, DF3ModuleSlot, 0x084C, 0 // Edge Driven Interrupt //)); */
for(chan = 1; chan<=16; chan++)
{
if (status == NAI_SUCCESS)
status = check_status(naibrd_DIF_SetEdgeLevelInterrupt(cardIndex, DF3ModuleSlot, chan, NAI_DIF_CTS_STATUS_RUN_LATCHED, NAI_DIF_EDGE_INTERRUPT));
}
/* Set up Interrupt Steering */
if (status == NAI_SUCCESS)
/* status = check_status(naibrd_Gen5_DirectInterrupts(cardIndex, DF3ModuleSlot, 5 //Interrupt Number//, NAIBRD_INT_STEERING_ON_BOARD_0)); */
status = check_status(naibrd_DIF_SetGroupInterruptSteering(cardIndex, DF3ModuleSlot, 1, NAI_DIF_CTS_STATUS_RUN_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0));
/* Enable to receive "CTS 1PPS Pulse" Interrupt */
if (status == NAI_SUCCESS)
/* status = check_status(naibrd_WriteReg32(cardIndex, DF3ModuleSlot, 0x0848, 0x0008)); */
status = check_status(naibrd_DIF_CTS_SetInterruptEnable(cardIndex, DF3ModuleSlot, NAI_DIF_CTS_INT_EXT_PULSE, 1));
return status;
}
/**************************************************************************************************************/
/**
<summary>
my_DF3_Isr is responsible for determining if a request was made to initialize (and synchronize across modules)
the counters (coarse and subsec). The counters are either initialized to a value well outside of the range of
the events that are to be loaded (in order to avoid the possibility of events being fired while still loading
the event table), or the counters are initialized to a value that is close to the counter value of the 1st event
that is assumed to have already been loaded.
</summary>
*/
/**************************************************************************************************************/
void my_DF3_Isr(void* param, uint32_t vector)
{
#if defined (_DEBUG_PRINT)
printf("In my_DF3_Isr\n");
#endif
/* If told to initialize course counter..now is the time to get counters synchronized! */
if (g_InitCounters > 0)
{
printf("Request to Init Counters detected\n");
if (g_DF3_FirstSlot != 0)
{
/* When Init Counters == 1, we set course counter to be well outside the range of events we are going to be loading */
if (g_InitCounters == 1)
/* naibrd_WriteReg32(g_CardIndex, g_DF3_FirstSlot, 0x0000120C, 0x00004000);*/
naibrd_DIF_CTS_SetCourseCounter(g_CardIndex, g_DF3_FirstSlot, 0x00004000);
else /*Set course counter to be close to the first event so we don't have to wait forever to see some activity */
/* naibrd_WriteReg32(g_CardIndex, g_DF3_FirstSlot, 0x0000120C, 0x000008F5); */
naibrd_DIF_CTS_SetCourseCounter(g_CardIndex, g_DF3_FirstSlot, (g_firstDF3Events[0].courseCounter - 5));
/* naibrd_WriteReg32(g_CardIndex, g_DF3_FirstSlot, 0x00001218, 0x00000000); */
naibrd_DIF_CTS_SetSubsecCounter(g_CardIndex, g_DF3_FirstSlot, 0x00000000);
}
if (g_DF3_SecondSlot != 0)
{
/* When Init Counters == 1, we set course counter to be well outside the range of events we are going to be loading */
if (g_InitCounters == 1)
/* naibrd_WriteReg32(g_CardIndex, g_DF3_SecondSlot, 0x0000120C, 0x00004000); */
naibrd_DIF_CTS_SetCourseCounter(g_CardIndex, g_DF3_SecondSlot, 0x00004000);
else /*Set course counter to be close to the first event so we don't have to wait forever to see some activity */
/* naibrd_WriteReg32(g_CardIndex, g_DF3_SecondSlot, 0x0000120C, 0x000008F5); */
naibrd_DIF_CTS_SetCourseCounter(g_CardIndex, g_DF3_SecondSlot, (g_firstDF3Events[0].courseCounter - 5));
/* naibrd_WriteReg32(g_CardIndex, g_DF3_SecondSlot, 0x00001218, 0x00000000); */
naibrd_DIF_CTS_SetSubsecCounter(g_CardIndex, g_DF3_SecondSlot, 0x00000000);
}
g_InitCounters = 0;
}
/* Now clear the interrupt we just handled */
/* naibrd_WriteReg32(g_CardIndex, g_DF3_FirstSlot, 0x0844, 0x0008); */
naibrd_DIF_CTS_ClearInterruptStatus(g_CardIndex, g_DF3_FirstSlot, NAI_DIF_CTS_INT_EXT_PULSE);
}