CTS DIF Ethernet
Edit this on GitLab
CTS DIF Ethernet
Explanation
NAI SSK Sample Application - Explanation
This C code is a sample application provided by North Atlantic Industries (NAI) for interacting with their embedded function modules using the SSK toolkit. The sample demonstrates configuring and controlling a Discrete I/O module (DIF) for a timing event system (CTS).
Key Components and Functionality
The application is organized into several key parts:
1. Include Files The code begins by including standard and NAI-specific header files necessary for function declarations and system constants.
-
Standard Libraries:
-
stdio.h
,stdlib.h
,string.h
,time.h
,ctype.h
-
NAI Libraries:
-
nai.h
,naibrd.h
,naibrd_dif.h
,naibrd_dif_cts.h
,nai_ether_adv.h
,naibrd_gen5.h
-
NAI sample program utilities:
-
naiapp_boardaccess_menu.h
,naiapp_boardaccess_query.h
,naiapp_boardaccess_access.h
,naiapp_boardaccess_display.h
,naiapp_boardaccess_utils.h
2. Constants and Enumerations
- Config Settings:
c
static const int8_t *CONFIG_FILE = "default_CTS_DIF_Ethernet.txt";
static const uint32_t EVENT_DETECTED = 0x00000040;
-
DIF CTS Commands: Enumerate command types for DIF CTS operations:
c enum dif_cts_commands { DIF_CTS_CMD_DEF, DIF_CTS_CMD_OUTPUT, DIF_CTS_CMD_FLUSH, DIF_CTS_CMD_INIT, DIF_CTS_CMD_COURSE, DIF_CTS_CMD_SUBSEC, DIF_CTS_CMD_LOAD, DIF_CTS_CMD_FILL, DIF_CTS_CMD_DEMO, DIF_CTS_CMD_COUNT };
3. Structures
- Event Struct:
Define the structure to hold event data.
c
struct _EventStruct {
int32_t courseCounter;
int32_t subSecCounter;
int32_t value;
};
4. Globals and Function Prototypes
- Global Variables:
c
#define MAX_EVENTS 5000
static struct _EventStruct g_firstDF3Events[MAX_EVENTS];
static struct _EventStruct g_secondDF3Events[MAX_EVENTS];
static uint32_t g_TotalEventCount = 0;
static int8_t g_SilentMode = 0;
static int8_t g_InitCounters = 0;
-
Function Prototypes: Function prototypes for DIF CTS operations are declared for use within the application.
5. Main Function
- Entry Point:
The main function is conditional based on whether the code is compiled for VxWorks or another platform. It allows user interaction via console to configure and control the DIF module.
c
#if defined (VXWORKS)
int32_t DIF_CTS(void)
#else
int32_t main(void)
#endif
6. Complementary Functions
- Run_DIF_CTS, Cfg_DIF_CTS:
Handle user commands for configuring and running DIF CTS operations.
c
int32_t Run_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t moduleID);
static void Cfg_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t ModuleID);
-
DIF Configuration Display and Command Implementations: Functions like
Display_DIF_CTS_Cfg
,Configure_DIF_CTS_Default
,Configure_DIF_CTS_Course
, andConfigure_DIF_CTS_Subsec
show module configurations and handle user inputs for various operations. -
Event Handling Functions: Functions such as
Load_DIF_CTS_Event
,run_DIF_CTS_demo
,init_DIF_System
, andload_DIF_FIFO
manage event data loading and demonstrations. -
Utility Functions: Utility functions like
map_DF3_EventValue
,reverseMap_DF3_EventValue
, andfill_Event_Struct
handle data mapping and parsing for event operations.
How It Works: 1. Initialization: - Configuration file is loaded, and the card index is queried from the user. - The module type is validated to ensure it is a DIF CTS module.
-
Command Execution:
-
Commands are presented to the user in a menu format to modify configurations, set counters, load events, flush queues, initiate clocks, etc.
-
Based on user commands, appropriate DIF CTS functions from the
naibrd
library are called.
-
-
Event Handling:
-
Events are loaded from an external file and are mapped to appropriate DIF module values.
-
The demonstration mode (
run_DIF_CTS_demo
) showcases the system’s functionality by loading event data, starting counters, and monitoring events.
-
-
Event Data Management:
-
Event data is structured, loaded, and displayed, facilitating the monitoring of I/O state changes based on configured events and counters.
-
This sample code provides a robust starting point for users working with NAI embedded systems, giving hands-on experience in configuring, controlling, and monitoring DIF modules using the SSK toolkit.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_dif.h"
#include "functions/naibrd_dif_cts.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.h"
static const int8_t *CONFIG_FILE = "default_CTS_DIF_Ethernet.txt";
static const uint32_t EVENT_DETECTED = 0x00000040;
/****** Command Table *******/
enum dif_cts_commands
{
DIF_CTS_CMD_DEF,
DIF_CTS_CMD_OUTPUT,
DIF_CTS_CMD_FLUSH,
DIF_CTS_CMD_INIT,
DIF_CTS_CMD_COURSE,
DIF_CTS_CMD_SUBSEC,
DIF_CTS_CMD_LOAD,
DIF_CTS_CMD_FILL,
DIF_CTS_CMD_DEMO,
DIF_CTS_CMD_COUNT
};
struct _EventStruct
{
int32_t courseCounter;
int32_t subSecCounter;
int32_t value;
};
#define MAX_EVENTS 5000
static struct _EventStruct g_firstDF3Events[MAX_EVENTS];
static struct _EventStruct g_secondDF3Events[MAX_EVENTS];
/* Function prototypes */
int32_t Run_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t moduleID);
static void Cfg_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t ModuleID);
void Display_DIF_CTS_Cfg(int32_t cardIndex, int32_t module, uint32_t ModuleID);
nai_status_t Configure_DIF_CTS_Default(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DIF_CTS_Course(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DIF_CTS_Subsec(int32_t paramCount, int32_t* p_params);
nai_status_t Load_DIF_CTS_Event(int32_t paramCount, int32_t* p_params);
void run_DIF_CTS_demo(int32_t cardIndex);
bool_t load_DIF_FIFO(int32_t cardIndex, int32_t DIFModuleSlot);
bool_t init_DIF_System(int32_t cardIndex, int32_t DIFModuleSlot1, int32_t DIFModuleSlot2, char const* DIFEventDataFile);
static void fill_Event_Struct(char* line, struct _EventStruct *eventStruct);
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue);
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue);
/****** Command Tables *******/
naiapp_cmdtbl_params_t DIF_CTSMenuCmds[] = {
{"Default", "DIF Set Default Output on Flush", DIF_CTS_CMD_DEF, Configure_DIF_CTS_Default},
{"Outputs", "DIF Set All Output Mode", DIF_CTS_CMD_OUTPUT, NULL},
{"Flush", "DIF Flush Queues", DIF_CTS_CMD_FLUSH, NULL},
{"Init", "DIF Clock Initiate", DIF_CTS_CMD_INIT, NULL},
{"Course", "DIF Set Course Counter", DIF_CTS_CMD_COURSE, Configure_DIF_CTS_Course},
{"Subsec", "DIF Set Subsec Counter", DIF_CTS_CMD_SUBSEC, Configure_DIF_CTS_Subsec},
{"Load", "DIF Load Event", DIF_CTS_CMD_LOAD, Load_DIF_CTS_Event},
{"Fill", "DIF Fill FIFO", DIF_CTS_CMD_FILL, NULL},
{"Demo", "DIF Run Demo", DIF_CTS_CMD_DEMO, NULL},
};
/* Global Variables */
static uint32_t g_TotalEventCount = 0;
static int8_t g_SilentMode = 0;
static int8_t g_InitCounters = 0;
/**************************************************************************************************************/
/**
<summary>
The purpose of the DIF_CTS is to illustrate the methods to call in the naibrd library to perform cts
operations with the discrete modules for configuration setup, setting counters, loading and firing
events.
The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd DIF routines.
- ClearDeviceCfg
- QuerySystemCfg
- DisplayDeviceCfg
- GetBoardSNModCfg
- SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DIF_CTS(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_DIF_CTS(cardIndex, module, moduleID);
}
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
Run_DIF_CTS prompts the user for the card, module and channel to use for the application and calls
Cfg_DIF_CTS if the card, module, channel is valid for as a discrete module.
</summary>
*/
/**************************************************************************************************************/
int32_t Run_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
int32_t MaxChannel;
MaxChannel = naibrd_DIF_GetChannelCount(moduleID);
if (MaxChannel == 0)
printf(" *** Module selection not recognized as DIF module. ***\n\n");
else
Cfg_DIF_CTS(cardIndex, module, moduleID);
return cardIndex;
}
/**************************************************************************************************************/
/**
<summary>
Cfg_DIF_CTS handles calling the Display_DIF_ChannelCfg routine to display the dif module configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
static void Cfg_DIF_CTS(int32_t cardIndex, int32_t module, uint32_t ModuleID)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
bool_t bCmdFound = FALSE;
int32_t cmd;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiapp_AppParameters_t ttl_params;
p_naiapp_AppParameters_t cts_eth_params = &ttl_params;
cts_eth_params->cardIndex = cardIndex;
cts_eth_params->module = module;
cts_eth_params->channel = 0;
while (bContinue)
{
printf(" \r\n\r\n");
naiapp_utils_LoadParamMenuCommands(DIF_CTS_CMD_COUNT, DIF_CTSMenuCmds);
while (bContinue)
{
Display_DIF_CTS_Cfg(cardIndex, module, ModuleID);
naiapp_display_ParamMenuCommands((int8_t *)"DIF CTS Operation Menu");
printf("\nType DIF command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case DIF_CTS_CMD_OUTPUT:
check_status(naibrd_WriteReg32(cardIndex, module, 0x00001038, 0x0000ffff));
break;
case DIF_CTS_CMD_FLUSH:
check_status(naibrd_DIF_CTS_FlushQueues(cardIndex, module));
printf("Queues have been flushed\n");
break;
case DIF_CTS_CMD_COURSE:
case DIF_CTS_CMD_SUBSEC:
case DIF_CTS_CMD_LOAD:
case DIF_CTS_CMD_DEF:
DIF_CTSMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)cts_eth_params);
break;
case DIF_CTS_CMD_FILL:
load_DIF_FIFO(cardIndex, module);
case DIF_CTS_CMD_INIT:
check_status(naibrd_DIF_CTS_ClockInitiate(cardIndex, module));
break;
case DIF_CTS_CMD_DEMO:
run_DIF_CTS_demo(cardIndex);
break;
default:
printf("Invalid command entered\n");
break;
}
}
else
printf("Invalid command entered\n");
}
}
else
bContinue = FALSE;
}
}
}
/**************************************************************************************************************/
/**
<summary>
Display_DIF_CTS_Cfg displays the dif module configuration which include I/O State and current course and
subsec counter values.
</summary>
*/
/**************************************************************************************************************/
void Display_DIF_CTS_Cfg(int32_t cardIndex, int32_t module, uint32_t ModuleID)
{
uint32_t outputstate = 0;
uint32_t coursecount = 0;
uint32_t subseccount = 0;
uint32_t outdefaultValue = 0;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
check_status(naibrd_DIF_GetGroupInputStateRaw(cardIndex, module, 1, &outputstate));
check_status(naibrd_DIF_CTS_GetCourseCounter(cardIndex, module, &coursecount));
check_status(naibrd_DIF_CTS_GetSubsecCounter(cardIndex, module, &subseccount));
check_status(naibrd_DIF_CTS_GetSwitchDefVal(cardIndex, module, &outdefaultValue));
printf("\n\n============== DIF CTS CFG ==============");
printf("\nI/O state : 0x%x", outputstate);
printf("\nCourse Count: 0x%x", coursecount);
printf("\nSubsec Count: 0x%x", subseccount);
printf("\nDefault Output Value: 0x%x", outdefaultValue);
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_CTS_Default handles the user request to set the default CIA switch value for the selected module
which is driven to the output when the flush queue command is called.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DIF_CTS_Default(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t defaultVal;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
p_naiapp_AppParameters_t cts_eth_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = cts_eth_params->cardIndex;
int32_t module = cts_eth_params->module;
int32_t chan = cts_eth_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(chan);
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\nEnter the desired default output value on flush: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
defaultVal = strtol((const char*)inputBuffer, NULL, 0);
switch (ModuleID)
{
case NAI_MODULE_ID_DF3:
if (defaultVal < 0)
{
printf("Invalid course counter entry.\n");
}
check_status(naibrd_DIF_CTS_SetSwitchDefVal(cardIndex, module, defaultVal));
break;
default:
printf("Unsupported function for this module.\n");
break;
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_CTS_Course handles the user request to set the course count for the selected module
and calls the method in the naibrd library to set the count.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DIF_CTS_Course(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t coursecount;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
p_naiapp_AppParameters_t cts_eth_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = cts_eth_params->cardIndex;
int32_t module = cts_eth_params->module;
int32_t chan = cts_eth_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(chan);
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\nEnter the desired course counter: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
coursecount = strtol((const char*)inputBuffer, NULL, 0);
switch (ModuleID)
{
case NAI_MODULE_ID_DF3:
if (coursecount < 0)
{
printf("Invalid course counter entry.\n");
}
check_status(naibrd_DIF_CTS_SetCourseCounter(cardIndex, module, coursecount));
break;
default:
printf("Unsupported function for this module.\n");
break;
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_CTS_Subsec handles the user request to set the subsec count for the selected module
and calls the method in the naibrd library to set the count.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DIF_CTS_Subsec(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t subseccount;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
p_naiapp_AppParameters_t cts_eth_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = cts_eth_params->cardIndex;
int32_t module = cts_eth_params->module;
int32_t chan = cts_eth_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(chan);
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\nEnter the desired subsec counter: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
subseccount = strtol((const char*)inputBuffer, NULL, 0);
switch (ModuleID)
{
case NAI_MODULE_ID_DF3:
if (subseccount < 0)
{
printf("Invalid subsec counter entry.\n");
}
check_status(naibrd_DIF_CTS_SetSubsecCounter(cardIndex, module, subseccount));
break;
default:
printf("Unsupported function for this module.\n");
break;
}
}
}
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_DIF_CTS_Event handles the user request to write event to the selected module and calls the method
in the naibrd library to load event. Event is made up of course count, subsec count and event data.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Load_DIF_CTS_Event(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit = FALSE;
uint32_t subseccount = 0, coursecount = 0, eventdata = 0;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
p_naiapp_AppParameters_t cts_eth_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = cts_eth_params->cardIndex;
int32_t module = cts_eth_params->module;
int32_t chan = cts_eth_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(chan);
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\nEnter the desired course for event: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit && inputResponseCnt > 0)
coursecount = strtol((const char*)inputBuffer, NULL, 0);
printf("Enter the desired subsec for event: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit && inputResponseCnt > 0)
subseccount = strtol((const char*)inputBuffer, NULL, 0);
printf("Enter the desired data for event: ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit && inputResponseCnt > 0)
{
eventdata = strtol((const char*)inputBuffer, NULL, 0);
}
if (!bQuit)
{
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
switch (ModuleID)
{
case NAI_MODULE_ID_DF3:
if (coursecount < 0)
printf("Invalid course count entry.\n");
if (subseccount < 0)
printf("Invalid subsec count entry.\n");
if (eventdata < 0)
printf("Invalid data entry.\n");
check_status(naibrd_DIF_CTS_WriteEvent(cardIndex, module, coursecount, subseccount, eventdata));
break;
default:
printf("Unsupported function for this module.\n");
break;
}
}
return (bQuit) ? NAI_ERROR_BIT_FAILED : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
run_DIF_CTS_demo is responsible for opening up the specified card; initializing the desired DIF CTS modules
with events and then monitoring for said events; Module is set up so events can be observed on the
"I/O" register when fired.
</summary>
*/
/**************************************************************************************************************/
void run_DIF_CTS_demo(int32_t cardIndex)
{
int32_t baseModule = 2;
int32_t syncModule = 3;
bool_t bQuit = FALSE, bContinue = TRUE;
uint32_t detectedEventCount = 0;
int32_t MaxChannel;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
uint32_t DF3CourseCounter = 0;
uint32_t DF3ExpectedCourseCounter = 0;
uint32_t DF3SubSecCounter = 0;
uint32_t DF3ExpectedSubSecCounter = 0;
uint32_t DF3ExpectedRawCompositeEventValue = 0;
uint32_t DF3CompositeReadBackValue = 0;
char DF3EventDataFile[20];
uint32_t firstDF3DetectedEventCount = 0;
uint32_t secondDF3DetectedEventCount = 0;
uint32_t firstDF3ModuleSlotStatus = 0;
uint32_t firstDF3ReadBackValue = 0;
uint32_t secondDF3ReadBackValue = 0;
printf("\n************************** DIF CTS DEMO RUN **************************\n");
g_TotalEventCount = 0;
/* check_status(naibrd_GetModuleCount(cardIndex, &MaxModule));*/
naibrd_GetModuleInfo(cardIndex, baseModule, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
MaxChannel = naibrd_DIF_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf("Setup not configured correctly for demo please check DIF module in slot %i\n", baseModule);
printf("\n**********************************************************************\n");
return;
}
naibrd_GetModuleInfo(cardIndex, syncModule, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
MaxChannel = naibrd_DIF_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf("Setup not configured correctly for demo please check DIF module in slot %i\n", syncModule);
printf("\n**********************************************************************\n");
return;
}
sprintf(DF3EventDataFile, "%s", "eventdata.txt");
/* Initialize Counters Outside of first event */
naibrd_DIF_CTS_SetCourseCounter(cardIndex, baseModule, 0x00004000);
naibrd_DIF_CTS_SetCourseCounter(cardIndex, syncModule, 0x00004000);
/* Now initialize each active D3 module with desired event data */
if (!init_DIF_System(cardIndex, baseModule, syncModule, DF3EventDataFile))
bQuit = TRUE;
/* Clear any leftover event interrupts */
naibrd_DIF_ClearGroupStatusRaw(cardIndex, baseModule, 1, NAI_DIF_CTS_STATUS_RUN_LATCHED, 0xFFFF);
/* Load Counter to value close to first event to be able to observe firing */
naibrd_DIF_CTS_SetCourseCounter(cardIndex, baseModule, 0x000008F3);
if (syncModule != 0 && syncModule != baseModule)
naibrd_DIF_CTS_SetCourseCounter(cardIndex, syncModule, 0x000008F3);
/* For Silent Mode - we just initialize the DIF CTS Module(s) and then exit */
if (bQuit)
printf("Error Opening event files\n");
else if (!g_SilentMode)
{
printf("=============================================================================\n");
printf("Waiting for %u events...\n", g_TotalEventCount);
while (bContinue)
{
DF3CompositeReadBackValue = 0;
DF3ExpectedRawCompositeEventValue = 0;
DF3ExpectedCourseCounter = 0;
DF3ExpectedSubSecCounter = 0;
if (baseModule != 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(cardIndex, baseModule, 0x00000844, &firstDF3ModuleSlotStatus);
if ((firstDF3ModuleSlotStatus & EVENT_DETECTED) == EVENT_DETECTED)
{
/* Clear the latch */
naibrd_WriteReg32(cardIndex, baseModule, 0x00000844, EVENT_DETECTED);
/* naibrd_ReadReg32(g_CardIndex, firstDF3ModuleSlot, 0x00001000, &firstDF3TempReadBackValue); */
naibrd_DIF_GetGroupInputStateRaw(cardIndex, baseModule, 1, &firstDF3ReadBackValue);
firstDF3ReadBackValue = reverseMap_DF3_EventValue(baseModule, firstDF3ReadBackValue);
naibrd_DIF_CTS_GetCourseCounter(cardIndex, baseModule, &DF3CourseCounter);
naibrd_DIF_CTS_GetSubsecCounter(cardIndex, baseModule, &DF3SubSecCounter);
DF3CompositeReadBackValue |= firstDF3ReadBackValue;
DF3ExpectedCourseCounter = g_firstDF3Events[firstDF3DetectedEventCount].courseCounter;
DF3ExpectedSubSecCounter = g_firstDF3Events[firstDF3DetectedEventCount].subSecCounter;
DF3ExpectedRawCompositeEventValue = g_firstDF3Events[firstDF3DetectedEventCount].value;
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 (syncModule != 0)
{
/* naibrd_ReadReg32(g_CardIndex, secondDF3ModuleSlot, 0x00001000, &secondDF3TempReadBackValue); */
naibrd_DIF_GetGroupInputStateRaw(cardIndex, syncModule, 1, &secondDF3ReadBackValue);
secondDF3ReadBackValue = reverseMap_DF3_EventValue(syncModule, secondDF3ReadBackValue);
naibrd_DIF_CTS_GetCourseCounter(cardIndex, syncModule, &DF3CourseCounter);
naibrd_DIF_CTS_GetSubsecCounter(cardIndex, syncModule, &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 (baseModule != 0 && syncModule != 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 */
}
}
}
/**************************************************************************************************************/
/**
<summary>
init_DIF_System is responsible for initializing a specific DIF 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 DIF module is read from a dedicated CSV file.
</summary>
*/
/**************************************************************************************************************/
bool_t init_DIF_System(int32_t cardIndex, int32_t DIFModuleSlot1, int32_t DIFModuleSlot2, char const* DIFEventDataFile)
{
FILE* file = NULL;
char line[256];
int32_t count = 0;
struct _EventStruct eventStruct;
/* Open the event file */
file = fopen(DIFEventDataFile, "r");
if (file != NULL)
{
/* Set all pins as output */
naibrd_WriteReg32(cardIndex, DIFModuleSlot1, 0x00001038, 0x0000ffff);
naibrd_WriteReg32(cardIndex, DIFModuleSlot2, 0x00001038, 0x0000ffff);
/* Flush all Queues */
naibrd_DIF_CTS_FlushQueues(cardIndex, DIFModuleSlot1);
naibrd_DIF_CTS_FlushQueues(cardIndex, DIFModuleSlot2);
/* Initiate Clock */
naibrd_DIF_CTS_ClockInitiate(cardIndex, DIFModuleSlot1);
printf("*****************************************************************************\n");
printf("DIF CTS Event Data\n");
printf("*****************************************************************************\n");
/* Initialize with events */
while (fgets(line, sizeof(line), file))
{
count++;
fill_Event_Struct(line, &eventStruct);
/* 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, eventStruct.courseCounter, eventStruct.subSecCounter, eventStruct.value);
/* Load the Event Table */
naibrd_DIF_CTS_WriteEvent(cardIndex, DIFModuleSlot1, eventStruct.courseCounter, eventStruct.subSecCounter, map_DF3_EventValue(DIFModuleSlot1, eventStruct.value));
naibrd_DIF_CTS_WriteEvent(cardIndex, DIFModuleSlot2, eventStruct.courseCounter, eventStruct.subSecCounter, map_DF3_EventValue(DIFModuleSlot2, eventStruct.value));
g_firstDF3Events[count - 1] = eventStruct;
/* g_firstDF3Events[count-1].value = map_DF3_EventValue(DIFModuleSlot1, eventStruct.value);*/
g_secondDF3Events[count - 1] = eventStruct;
/*g_secondDF3Events[count-1].value = map_DF3_EventValue(DIFModuleSlot2, eventStruct.value);*/
g_TotalEventCount++;
}
printf("\n");
fclose(file);
return TRUE;
}
else
return FALSE;
}
/**************************************************************************************************************/
/**
<summary>
load_DIF_FIFO is responsible for 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 DIF module is read from a dedicated CSV file.
</summary>
*/
/**************************************************************************************************************/
bool_t load_DIF_FIFO(int32_t cardIndex, int32_t DIFModuleSlot)
{
FILE* file = NULL;
char file_name[256];
char line[256];
struct _EventStruct eventStruct_FIFO;
printf("Please event file name:");
gets(file_name);
/* Open the event file */
/* file = fopen("eventdata.txt", "r"); */
file = fopen(file_name, "r");
if (file != NULL)
{
printf("*****************************************************************************\n");
printf("DIF CTS Event Data\n");
printf("*****************************************************************************\n");
/* Initialize with events */
while (fgets(line, sizeof(line), file))
{
/* count++; */
fill_Event_Struct(line, &eventStruct_FIFO);
/* Load the Event Table */
naibrd_DIF_CTS_WriteEvent(cardIndex, DIFModuleSlot, eventStruct_FIFO.courseCounter, eventStruct_FIFO.subSecCounter, eventStruct_FIFO.value);
}
printf("Events Loaded!!\n");
fclose(file);
return TRUE;
}
else
{
printf("Failed to Load Event File!!!*******\n");
return FALSE;
}
}
/**************************************************************************************************************/
/**
<summary>
map_DF3_EventValue is responsible for mapping out event data so that the data corresponds to bit per channel
</summary>
*/
/**************************************************************************************************************/
static int32_t map_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue)
{
int32_t nMappedEventValue = 0;
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;
}
return nMappedEventValue;
}
/**************************************************************************************************************/
/**
<summary>
reverseMap_DF3_EventValue is responsible for reverse mapping data read from the module into data format
expected.
</summary>
*/
/**************************************************************************************************************/
static int32_t reverseMap_DF3_EventValue(int32_t DF3ModuleSlot, int32_t nEventValue)
{
int32_t nReversedMappedEventValue = 0;
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;
}
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(char* line, struct _EventStruct *eventStruct)
{
const char* tok;
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)
eventStruct->value = (int32_t)strtol(tok, NULL, 0);
}
}
}