SER ASync GPIO
Edit this on GitLab
SER ASync GPIO
Explanation
About the Sample Application Code
The provided sample application code from North Atlantic Industries demonstrates how to interact with their function modules, specifically to configure a serial channel for GPIO (General Purpose Input/Output) mode and toggle the output in a loopback configuration. Below is a detailed walkthrough of the application code and important definitions.
Header Files
The code includes several header files:
- Standard Libraries: stdio.h
, stdlib.h
, string.h
, time.h
, and ctype.h
.
- Common Sample Program Header Files: These headers provide functions for board access, querying, display, and utility functions required by the sample program.
- naiapp_boardaccess_menu.h
- naiapp_boardaccess_query.h
- naiapp_boardaccess_access.h
- naiapp_boardaccess_display.h
- naiapp_boardaccess_utils.h
- NAI-Specific Headers:
- nai.h
: Contains core definitions for NAI.
- naibrd.h
: Contains definitions for board-related operations.
- naibrd_ser.h
: Contains functions specific to the serial module.
- nai_ether_adv.h
: Advanced functions for Ethernet communication (not used in this code).
Constants and Function Prototypes
- Constants:
- CONFIG_FILE
: Points to the configuration file "default_SerASync_GPIO.txt".
- CLEAR_FIFO_TIMEOUT
: Defines the timeout value for clearing FIFOs (1 second).
- Function Prototypes:
- void Run_SER_ASync_GPIO(int32_t cardIndex, int32_t module, uint32_t moduleID);
: Prototype for the function that handles GPIO operations.
Main Function
Main Function for Different Operating Systems
The main function is defined differently for VxWorks (int32_t SER_ASync_GPIO_Sample(void)
) and for other systems (int32_t main(void)
).
Main Function Workflow
1. Initialize Variables:
- stop
: Boolean to control the main loop.
- cardIndex
, moduleCnt
, module
: Integers to store card and module information.
- moduleID
: Stores the ID of the module.
- inputBuffer
: Buffer to store user input.
- inputResponseCnt
: Counts responses from the user.
-
Run Board Menu:
-
naiapp_RunBoardMenu(CONFIG_FILE)
: Initializes the board menu with the provided configuration file.
-
-
Main Loop:
-
Query the user for the card index using
naiapp_query_CardIndex
. -
Retrieve the module count on the selected card using
naibrd_GetModuleCount
. -
Query the user for the module number using
naiapp_query_ModuleNumber
. -
Retrieve the module ID using
naibrd_GetModuleID
. -
If the module is the NAI SC3 module, call
Run_SER_ASync_GPIO
to configure GPIO and begin operations. -
Prompt the user to quit or restart the application.
-
-
Exit and Cleanup:
-
Prompt the user to exit the program.
-
Close all open card connections using
naiapp_access_CloseAllOpenCards
.
-
Run_SER_ASync_GPIO Function This function configures a serial module for GPIO mode and allows the user to toggle the output and monitor the input.
Run_SER_ASync_GPIO Workflow
1. Initialize Variables:
- ch
, i
, channelCount
, chanNum
, nCntlValueLo
, control
, inputBuffer
, inputResponseCnt
: Variables for channel operations and user interaction.
- bQuit
: Boolean to control the loop for toggling GPIO.
-
Channel Operations:
-
Get the number of channels using
naibrd_SER_GetChannelCount
. -
Query the user for the channel number using
naiapp_query_ChannelNumber
. -
Reset the selected channel and clear its FIFOs using
naibrd_SER_ChannelReset
,naibrd_SER_ClearRxFifo
, andnaibrd_SER_ClearTxFifo
. -
Ensure the FIFOs are cleared within the timeout period.
-
-
Configure GPIO and Loopback:
-
Set the interface level to loopback with GPIO using
naibrd_SER_SetInterfaceLevel
. -
Enable the receiver using
naibrd_SER_SetReceiverEnable
. -
Add a delay for configuration stabilization.
-
Ensure General Purpose Output (GPO) is set to low initially.
-
-
User Interaction Loop:
-
Toggle GPO high and low based on user input.
-
Display General Purpose Input (GPI) status, which is tied to GPO in loopback mode.
-
Continue the loop until the user chooses to quit.
-
Summary
This sample application illustrates how to configure and monitor Serial General Purpose I/O on NAI embedded function modules. The code allows user interaction for selecting cards, modules, and channels, demonstrating a practical way to interface with NAI boards. The primary objective is to familiarize users with calling functions from the naibrd
library to control serial channels in GPIO mode.
#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_ser.h"
#include "advanced/nai_ether_adv.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_SerASync_GPIO.txt";
/* Function prototypes */
void Run_SER_ASync_GPIO(int32_t cardIndex, int32_t module, uint32_t moduleID);
#define CLEAR_FIFO_TIMEOUT 1000 /* 1 second */
/**************************************************************************************************************/
/** \defgroup SERGPIO Serial General Purpose I/O
The purpose of the Serial General Purpose I/O sample application is to illustrate the methods to call in the
naibrd library to configure a given serial channel for GPIO mode and toggle the output. In loopback, the general
purpose input and general purpose output lines are connected together.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_ASync_GPIO_Sample(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 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) && (moduleID == NAI_MODULE_ID_SC3))
{
Run_SER_ASync_GPIO(cardIndex, module, moduleID);
}
else
{
printf("\nThe GPIO feature is only available on the NAI SC3 module.\n\n");
}
}
}
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;
}
/**************************************************************************************************************/
/** \ingroup SERGPIO
Configures a serial module for GPIO mode. The user can than the toggle the general purpose output
and monitor the general purpose input.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param module (Input) Module Number of the module to access (1 - [max modules for board]).
\param moduleID (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_SER_ASync_GPIO(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
int32_t ch, i;
int32_t channelCount;
int32_t chanNum;
int32_t nCntlValueLo;
bool_t bQuit = FALSE;
uint32_t control = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
channelCount = naibrd_SER_GetChannelCount(moduleID);
naiapp_query_ChannelNumber(channelCount, 1, &chanNum);
naibrd_SER_ChannelReset(cardIndex, module, chanNum);
naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);
nCntlValueLo = NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO;
for (i = 0; i < CLEAR_FIFO_TIMEOUT && (nCntlValueLo & (NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO)); i++)
{
nai_ser_chanctrl chanCtrlRaw;
naibrd_SER_GetChannelControlRaw(cardIndex, module, chanNum, &chanCtrlRaw);
nCntlValueLo = chanCtrlRaw & 0x0000FFFF;
nai_msDelay(1);
}
if (i == CLEAR_FIFO_TIMEOUT)
{
printf("Unable to clear FIFOs %d\n", chanNum);
printf("Please press Enter to exit...");
while ((ch = getchar()) != 0x0A);
return;
}
printf("\nSerial Channel # %d\n", chanNum);
/* Configure GPIO + Loopback on the channel selected */
check_status(naibrd_SER_SetInterfaceLevel(cardIndex, module, chanNum, NAI_SER_INTF_LOOPBACK | NAI_SER_GEN5_INTF_GP_OUT)); /* LoopBack with GPIO */
/* Enable receiver */
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, TRUE));
/* Add a delay here for the configuration to be ready */
nai_msDelay(500);
/* Ensure GPO is low */
check_status(naibrd_SER_GetChannelControlRaw(cardIndex, module, chanNum, &control));
control &= ~NAI_SER_GEN5_CTRL_GPO1;
check_status(naibrd_SER_SetChannelControlRaw(cardIndex, module, chanNum, control));
do
{
printf("Press ENTER to pull GPO high, or %c to exit program...\n", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (TRUE != bQuit)
{
uint32_t chanStatus = 0;
/* Set the GPO bit to 1 (high state) */
control |= NAI_SER_GEN5_CTRL_GPO1;
check_status(naibrd_SER_SetChannelControlRaw(cardIndex, module, chanNum, control));
/* Since LOOPBACK mode ties GPO to GPI, GPI will be in a high state */
check_status(naibrd_SER_GetChannelStatusEx(cardIndex, module, chanNum, NAI_SER_STATUS_REALTIME, &chanStatus));
printf("GPI bit: %u\n", (chanStatus & NAI_SER_GEN5_INT_GPI1) >> 15);
printf("Press ENTER to pull GPO low, or %c to exit program...\n", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
if (TRUE != bQuit)
{
uint32_t chanStatus = 0;
/* Set the GPO bit to 0 (low state) */
control &= ~NAI_SER_GEN5_CTRL_GPO1;
check_status(naibrd_SER_SetChannelControlRaw(cardIndex, module, chanNum, control));
/* Since LOOPBACK mode ties GPO to GPI, GPI will be in a low state */
check_status(naibrd_SER_GetChannelStatusEx(cardIndex, module, chanNum, NAI_SER_STATUS_REALTIME, &chanStatus));
printf("GPI bit: %u\n", (chanStatus & NAI_SER_GEN5_INT_GPI1) >> 15);
}
} while (TRUE != bQuit);
return;
}