PRNT BasicOps
Edit this on GitLab
PRNT BasicOps Sample Application (SSK 1.x)
Overview
The PRNT BasicOps sample application demonstrates how to configure and operate a parallel printer port module using the NAI Software Support Kit (SSK 1.x). NAI printer modules implement a Centronics-style parallel interface that receives 7-bit data words along with parity, strobe, demand, ready, and status handshake signals. The module captures incoming print data into a hardware receive FIFO, making it available for software readout. This is the interface historically used by military and avionics systems for cockpit printers, data loggers, and maintenance recorders.
The sample covers the core printer operations you will need in your own application: resetting the printer channel, enabling and disabling the port, configuring I/O line termination resistors, reading received data from the hardware FIFO, and monitoring both channel status and FIFO status through real-time and latched registers.
This sample supports the DF4 module type (NAI_MODULE_ID_DF4), which provides one parallel printer port channel.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a DF4 printer module installed.
-
SSK 1.x installed on your development host.
-
The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.
How to Run
Launch the PRNT_BasicOps executable from your build output directory. On startup the application looks for a configuration file (default_PRNT_BasicOps.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, a command menu lets you exercise each printer operation.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to PRNT. For details on board connection configuration, see the First Time Setup Guide. |
The main() function follows a standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_PRNT_BasicOps.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()so downstream code can confirm that the selected slot contains a printer module.
#if defined (__VXWORKS__)
int32_t PRNT_BasicOps(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)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_PRNT_BasicOps(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;
}
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms the entry point is main(). On VxWorks the entry point is PRNT_BasicOps() — the SSK 1.x build system selects the correct variant via a preprocessor guard:
#if defined (__VXWORKS__)
int32_t PRNT_BasicOps(void)
#else
int32_t main(void)
#endif
The startup flow is the same in both cases:
-
Attempt to load the saved configuration file via
naiapp_RunBoardMenu(CONFIG_FILE). If the file does not yet exist, the interactive board menu is presented instead. -
Enter a loop that queries for card index and module slot.
-
Call
Run_PRNT_BasicOps()to validate the module type and enter the interactive command loop. -
On exit, close all open board connections with
naiapp_access_CloseAllOpenCards().
Module Validation
Before entering the command loop, Run_PRNT_BasicOps() calls naibrd_PRNT_GetChannelCount() with the detected module ID to verify that the selected slot actually contains a printer module. If the channel count is zero, the module is not a recognized PRNT type and the function returns immediately with an error message.
int32_t MaxChannel;
MaxChannel = naibrd_PRNT_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf(" *** Module selection not recognized as PRNT module. ***\n\n");
}
else
{
Cfg_PRNT_Channel(cardIndex, module, ModuleID, MaxChannel);
}
Application Parameters
The Cfg_PRNT_Channel() function populates an naiapp_AppParameters_t struct that is passed to every command handler. Your application will need to track these same values to identify which board, module, and channel you are targeting:
prnt_basicops_params->cardIndex = cardIndex;
prnt_basicops_params->module = module;
prnt_basicops_params->channel = chan;
prnt_basicops_params->modId = ModuleID;
prnt_basicops_params->maxChannels = MaxChannel;
-
cardIndex— identifies which board in a multi-board system. -
module— the slot number where the PRNT module is installed. -
channel— the currently selected channel (defaults to 1). The DF4 module has a single channel. -
modId— the module identifier returned bynaibrd_GetModuleID(). API functions use this to apply module-specific behavior. -
maxChannels— total channel count for the detected module, retrieved by callingnaibrd_PRNT_GetChannelCount()with the module ID.
Command Loop
Cfg_PRNT_Channel() drives the interactive command loop. On each iteration it displays the current channel configuration, prints the command menu, and dispatches the user’s selection to the matching handler function:
while (bContinue)
{
naiapp_utils_LoadParamMenuCommands(PRNT_BASICOP_CMD_COUNT, PRNT_BasicOpMenuCmds);
while (bContinue)
{
Display_PRNT_ChannelCfg(cardIndex, module, chan, ModuleID);
naiapp_display_ParamMenuCommands((int8_t *)"PRNT Basic Operation Menu");
printf("\nType PRNT 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)
{
PRNT_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT,
(int32_t*)prnt_basicops_params);
}
}
}
else
bContinue = FALSE;
}
}
The available commands are registered in the PRNT_BasicOpMenuCmds[] table:
| Command | Description |
|---|---|
Reset |
Toggle printer reset |
Termination |
Set I/O termination resistors |
Enable |
Toggle printer enable/disable |
Fifo |
Read and display FIFO data |
Clear status |
Clear latched channel status |
CF |
Clear latched FIFO status |
The menu-driven structure is a convenience of the sample application. In your own application, you would call the same underlying naibrd_PRNT_*() API functions directly — for example, calling naibrd_PRNT_SetControl() instead of navigating to the "Reset" menu command.
Printer Control
This section covers the API calls used to control the printer port: resetting the channel and enabling or disabling the printer interface. These two operations use the same underlying control register, accessed through naibrd_PRNT_SetControl() and naibrd_PRNT_GetControl().
Reset Printer
To reset the printer channel in your own application, call naibrd_PRNT_SetControl() with the NAI_PRNT_CONTROL_RESET flag. A reset clears the channel’s internal state, including the receive FIFO and all status registers. This is useful during initialization to ensure the channel starts from a known state, or during error recovery if the FIFO has overflowed or data has become corrupted.
The sample implements this as a toggle: it reads the current reset state, then writes the inverted value. In your own code you can set the reset bit directly.
uint32_t controlData = 0;
nai_status_t status;
/* Read current reset state */
status = naibrd_PRNT_GetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_RESET, &controlData);
if (status == NAI_SUCCESS)
{
/* Toggle reset: if reset was off, turn it on (and vice versa) */
status = naibrd_PRNT_SetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_RESET, ~controlData);
}
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
NAI_PRNT_CONTROL_RESET(0x00000004) — the control bitmask that selects the reset function. -
controlData— receives the current state of the reset bit. The bitwise complement~controlDatatoggles it.
|
Note
|
Asserting reset clears the receive FIFO. Any unread data in the FIFO will be lost when you toggle reset. Read the FIFO before resetting if you need to preserve pending data. |
Enable / Disable Printer
To enable or disable the printer port in your own application, call naibrd_PRNT_SetControl() with the NAI_PRNT_CONTROL_ENABLE flag. When disabled, the printer port does not capture incoming data — the strobe handshake is ignored and no data enters the receive FIFO. You must enable the port before the module will begin receiving print data.
At the hardware level, enabling the printer activates the parallel port receiver circuitry. The module then monitors the strobe line and latches each incoming data byte (D0-D6 plus parity) into the receive FIFO on the appropriate strobe edge.
uint32_t controlData;
/* Read the current enable state */
naibrd_PRNT_GetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_ENABLE, &controlData);
/* Toggle enable: if enabled, disable (and vice versa) */
naibrd_PRNT_SetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_ENABLE, ~controlData);
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
NAI_PRNT_CONTROL_ENABLE(0x00000001) — the control bitmask that selects the enable function.
To explicitly enable the printer without toggling, pass a nonzero value for the data parameter:
/* Explicitly enable the printer port */
naibrd_PRNT_SetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_ENABLE, NAI_PRNT_CONTROL_ENABLE);
/* Explicitly disable the printer port */
naibrd_PRNT_SetControl(cardIndex, module, channel,
NAI_PRNT_CONTROL_ENABLE, 0x00000000);
|
Important
|
Common Errors
|
I/O Line Termination
The parallel printer interface consists of twelve signal lines: seven data lines (D0-D6), one parity line, and four handshake lines (strobe, demand, ready, status). Each of these lines has an independently controllable termination resistor on the module. Termination resistors reduce signal reflections on long cable runs and improve noise immunity, which is especially important in electrically noisy avionics environments. However, if the cable is short or the driving device already provides proper termination, enabling the on-board resistors can cause excessive loading and distort signals.
To configure termination resistors in your own application, call naibrd_PRNT_SetTerminationEnable() with a bitmask specifying which lines to modify and the desired values.
nai_prnt_termination_enable_t terminationBits;
uint32_t terminationBitValuesSet;
/* Select which termination lines to modify */
terminationBits = NAI_PRNT_TERM_ENABLE_D0 | NAI_PRNT_TERM_ENABLE_D1;
/* Set the values: 1 = termination enabled, 0 = termination disabled */
terminationBitValuesSet = NAI_PRNT_TERM_ENABLE_D0 | NAI_PRNT_TERM_ENABLE_D1;
/* Apply the termination settings */
naibrd_PRNT_SetTerminationEnable(cardIndex, module, channel,
terminationBits, terminationBitValuesSet);
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
terminationBits— a bitmask selecting which lines to modify. Only the lines whose bits are set in this mask will be affected. -
terminationBitValuesSet— the desired state for the selected lines. A1bit enables the termination resistor on that line; a0bit disables it.
The available termination bits are:
| Constant | Value | Signal |
|---|---|---|
|
|
Data bit 0 |
|
|
Data bit 1 |
|
|
Data bit 2 |
|
|
Data bit 3 |
|
|
Data bit 4 |
|
|
Data bit 5 |
|
|
Data bit 6 |
|
|
Parity line |
|
|
Strobe handshake |
|
|
Demand handshake |
|
|
Ready handshake |
|
|
Status handshake |
To enable termination on all lines at once, pass 0x0FFF for both the mask and the value. To read back the current termination configuration, call naibrd_PRNT_GetTerminationEnable():
uint32_t terminationState = 0;
/* Read current termination state for all lines */
naibrd_PRNT_GetTerminationEnable(cardIndex, module, channel,
(nai_prnt_termination_enable_t)0xFFFFFFFFu, &terminationState);
|
Important
|
Common Errors
|
FIFO Data Operations
The printer module captures incoming parallel data into a 1024-entry hardware receive FIFO. Each FIFO entry holds one received data word (the 7 data bits, parity, and associated handshake state packed into a 32-bit register value). The FIFO operates on a first-in-first-out basis: data is stored in the order it arrives from the external device, and your application reads it out in the same order.
The FIFO has built-in threshold monitoring. The hardware tracks five conditions: empty, almost empty (fewer than 205 entries), almost full (more than 819 entries), full (1024 entries), and overflow (data arrived when the FIFO was already full and the new data was lost). These thresholds are defined in the header as NAI_PRNT_FIFO_ALMOST_EMPTY_THRESHOLD (205), NAI_PRNT_FIFO_ALMOST_FULL_THRESHOLD (819), and NAI_PRNT_FIFO_FULL_THRESHOLD (1024).
Reading the Receive FIFO
To read data from the printer receive FIFO in your own application, call naibrd_PRNT_ReadRxFIFO(). This function reads up to the requested number of entries from the FIFO, returns them in the output buffer, and reports how many entries were actually read and how many remain in the FIFO.
uint32_t rxFifoData[NAI_PRNT_FIFO_SIZE];
uint32_t countRemaining = 0;
uint32_t readCount = 0;
int32_t bufferIndex;
/* Zero the receive buffer */
for (bufferIndex = 0; bufferIndex < NAI_PRNT_FIFO_SIZE; bufferIndex++)
rxFifoData[bufferIndex] = 0;
/* Read all available data from the FIFO */
naibrd_PRNT_ReadRxFIFO(cardIndex, module, channel, NAI_PRNT_FIFO_SIZE,
&countRemaining, rxFifoData, &readCount);
/* Process the received data */
for (bufferIndex = 0; bufferIndex < (int32_t)readCount; bufferIndex++)
{
printf("%2u) 0x%08X\n", bufferIndex + 1, rxFifoData[bufferIndex]);
}
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
NAI_PRNT_FIFO_SIZE(1024) — the maximum number of entries to read. Pass a smaller value if you only need a partial read. -
countRemaining— after the call, holds the number of entries still in the FIFO. If this is nonzero, additional reads are needed to drain the FIFO completely. -
rxFifoData— the output buffer. Must be large enough to hold the requested number of entries. -
readCount— after the call, holds the number of entries actually read. This may be less than the requested count if the FIFO contained fewer entries.
Checking FIFO Count
To check how many entries are currently in the FIFO without reading them, call naibrd_PRNT_GetRxFIFOCount(). This is useful for polling the FIFO level before deciding whether to perform a read.
uint32_t fifoCount = 0;
naibrd_PRNT_GetRxFIFOCount(cardIndex, module, channel, &fifoCount);
|
Important
|
Common Errors
|
Status Monitoring
The printer module provides two layers of status reporting: channel status and FIFO status. Each layer has both a real-time register (reflecting the current instantaneous condition) and a latched register (which captures a condition and holds it until explicitly cleared by software). This dual-register design ensures that transient conditions — such as a brief data-available pulse or a momentary FIFO-full event — are not missed even if your software is not polling at the exact moment they occur.
Reading Channel Status
To read the printer channel status in your own application, call naibrd_PRNT_GetStatusRaw() with the appropriate status type. The channel status register has a single flag:
-
NAI_PRNT_STATUS_DATA_AVAILABLE(0x00000001) — indicates that data is present in the receive FIFO and available for reading.
nai_prnt_status_t statusRT = 0;
nai_prnt_status_t statusLT = 0;
/* Read real-time channel status */
naibrd_PRNT_GetStatusRaw(cardIndex, module, channel,
NAI_PRNT_STATUS_TYPE_REALTIME, &statusRT);
/* Read latched channel status */
naibrd_PRNT_GetStatusRaw(cardIndex, module, channel,
NAI_PRNT_STATUS_TYPE_LATCHED, &statusLT);
/* Check if data is available */
if (statusRT & NAI_PRNT_STATUS_DATA_AVAILABLE)
{
/* FIFO has data ready to read */
}
-
NAI_PRNT_STATUS_TYPE_REALTIME— reads the current instantaneous status. This bit clears automatically when the condition is no longer present (for example, when the FIFO becomes empty after a read). -
NAI_PRNT_STATUS_TYPE_LATCHED— reads the latched status. Once set, this bit remains set until explicitly cleared by software, even if the underlying condition has since resolved.
Clearing Latched Channel Status
To clear latched channel status bits in your own application, call naibrd_PRNT_ClearStatus() with a bitmask of the bits to clear. This is necessary to acknowledge a latched condition and allow the latch to capture a new event.
/* Clear the data-available latched status */
naibrd_PRNT_ClearStatus(cardIndex, module, channel,
NAI_PRNT_STATUS_DATA_AVAILABLE);
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
The fourth parameter is a bitmask of status bits to clear. For the PRNT module, the only valid bit is
NAI_PRNT_STATUS_DATA_AVAILABLE(0x00000001).
Reading FIFO Status
To read the FIFO status in your own application, call naibrd_PRNT_GetFIFOStatusRaw(). The FIFO status register provides finer-grained information about the state of the receive FIFO:
| Flag | Value | Meaning |
|---|---|---|
|
|
FIFO contains zero entries |
|
|
FIFO contains fewer than 205 entries |
|
|
FIFO contains more than 819 entries |
|
|
FIFO contains 1024 entries (capacity reached) |
|
|
Data was lost because the FIFO was full when new data arrived |
nai_prnt_fifo_status_t fifoStatusRT = 0;
nai_prnt_fifo_status_t fifoStatusLT = 0;
/* Read real-time FIFO status */
naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, channel,
NAI_PRNT_STATUS_TYPE_REALTIME, &fifoStatusRT);
/* Read latched FIFO status */
naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, channel,
NAI_PRNT_STATUS_TYPE_LATCHED, &fifoStatusLT);
/* Check for overflow condition */
if (fifoStatusLT & NAI_PRNT_FIFO_STATUS_OVERFLOW)
{
/* Overflow has occurred at some point -- data was lost */
}
The real-time FIFO status reflects the current state of the FIFO. The latched FIFO status captures conditions that have occurred at any point since the last clear. For example, if the FIFO briefly filled to capacity and then your application drained it, the real-time FULL flag would be clear but the latched FULL flag would remain set, indicating that the FIFO was full at some point.
Clearing Latched FIFO Status
To clear latched FIFO status bits in your own application, call naibrd_PRNT_ClearFIFOStatus() with a bitmask of the bits to clear.
/* Clear all latched FIFO status bits */
naibrd_PRNT_ClearFIFOStatus(cardIndex, module, channel,
NAI_PRNT_FIFO_STATUS_EMPTY | NAI_PRNT_FIFO_STATUS_ALMOST_EMPTY |
NAI_PRNT_FIFO_STATUS_ALMOST_FULL | NAI_PRNT_FIFO_STATUS_FULL |
NAI_PRNT_FIFO_STATUS_OVERFLOW);
-
cardIndex— identifies the board. -
module— the slot containing the PRNT module. -
channel— the printer channel (1 for DF4). -
The fourth parameter is a bitmask of FIFO status bits to clear. Pass
0x001Fto clear all five flags at once, or pass individual flags to clear specific conditions.
|
Important
|
Common Errors
|
Display Configuration
The Display_PRNT_ChannelCfg() function demonstrates the full set of naibrd_PRNT_Get* read-back APIs. These are the same calls you would use in your own application to retrieve the channel’s current state. The sample calls them on every iteration of the command loop to show a live view of the channel configuration.
nai_prnt_control_t control = 0;
nai_prnt_termination_enable_t terminationEnable = 0;
nai_prnt_status_t statusRT = 0, statusLT = 0;
nai_prnt_fifo_status_t fifoStatusRT = 0, fifoStatusLT = 0;
uint32_t fifoCount = 0;
uint32_t ModuleVer, ModuleRev, ModInfo_Special;
naibrd_GetModuleInfo(cardIndex, module, &ModuleID,
&ModuleVer, &ModuleRev, &ModInfo_Special);
naibrd_PRNT_GetControl(cardIndex, module, chan,
NAI_PRNT_CONTROL_ENABLE | NAI_PRNT_CONTROL_RESET, (uint32_t*)&control);
naibrd_PRNT_GetTerminationEnable(cardIndex, module, chan,
(nai_prnt_termination_enable_t)0xFFFFFFFFu, (uint32_t*)&terminationEnable);
naibrd_PRNT_GetStatusRaw(cardIndex, module, chan,
NAI_PRNT_STATUS_TYPE_REALTIME, &statusRT);
naibrd_PRNT_GetStatusRaw(cardIndex, module, chan,
NAI_PRNT_STATUS_TYPE_LATCHED, &statusLT);
naibrd_PRNT_GetRxFIFOCount(cardIndex, module, chan, &fifoCount);
naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, chan,
NAI_PRNT_STATUS_TYPE_REALTIME, &fifoStatusRT);
naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, chan,
NAI_PRNT_STATUS_TYPE_LATCHED, &fifoStatusLT);
The display output presents all of this information in a single table row:
-
Control — the enable and reset states (1 = active, 0 = inactive).
-
Termination — the termination enable register as a hex value showing which I/O lines have termination resistors enabled.
-
Status (R/L) — the real-time and latched data-available flags.
-
FIFO Count — the number of entries currently in the receive FIFO.
-
FIFO Status (R/L) — the real-time and latched FIFO status flags: empty, almost empty, almost full, full, and overflow.
-
naibrd_GetModuleInfo()— retrieves the module ID, version, revision, and special info fields. Useful for logging or for branching on module-specific behavior. -
naibrd_PRNT_GetControl()— reads the specified control bits. Pass a bitmask to read multiple control bits at once. -
naibrd_PRNT_GetTerminationEnable()— reads the termination enable state. Pass0xFFFFFFFFas the mask to read all bits. -
naibrd_PRNT_GetStatusRaw()— reads the raw status register for the specified status type. -
naibrd_PRNT_GetRxFIFOCount()— reads the current FIFO entry count. -
naibrd_PRNT_GetFIFOStatusRaw()— reads the raw FIFO status register for the specified status type.
Troubleshooting Reference
This table summarizes common errors and symptoms covered in the sections above. For detailed context on each entry, refer to the relevant section. Consult your module’s manual for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, incorrect or missing configuration file, network issue |
Verify hardware is powered and connected. If |
Module not detected at selected slot |
No module installed at the specified slot, incorrect module number entered |
Verify hardware configuration and module slot assignment. Call |
|
Feature not available for this module type, or the selected slot does not contain a printer module |
Check your module type. Verify the module ID returned by |
|
Invalid parameter passed to an API call (e.g., out-of-range termination bitmask, invalid channel number) |
Verify input values against the defined constants in |
|
Generic failure during an API call |
Check board connection, verify module is powered and responsive. |
FIFO read returns zero entries |
Printer port not enabled, no external data source connected, cable issue |
Verify the enable state with |
FIFO overflow (data lost) |
Data arriving faster than software reads it, FIFO not drained frequently enough |
Increase polling frequency or read larger batches. Monitor the |
Latched status bit re-asserts immediately after clearing |
Underlying condition is still active (e.g., clearing EMPTY latch when FIFO is actually empty) |
This is expected behavior. The latch will re-assert as long as the condition persists. |
Signal integrity or data corruption |
Incorrect termination configuration, long cable without termination, double-termination |
Review I/O termination settings. Enable termination resistors for lines that need them based on your cable length and driving device characteristics. |
Data-available status set but FIFO read returns stale data |
Reset was toggled after data arrived, clearing the FIFO without clearing the latched status |
Clear latched status after a reset to synchronize the status registers with the FIFO state. |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — PRNT_BasicOps.c (SSK 1.x)
#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_prnt.h"
#include "advanced/nai_ether_adv.h"
static const int8_t *CONFIG_FILE = (int8_t *)"default_PRNT_BasicOps.txt";
/* Function prototypes */
static int32_t Run_PRNT_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID);
static void Cfg_PRNT_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
static void Display_PRNT_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
static nai_status_t ResetPrinter(int32_t paramCount, int32_t* p_params);
static nai_status_t SetIOTermination(int32_t paramCount, int32_t* p_params);
static nai_status_t EnablePrinter(int32_t paramCount, int32_t* p_params);
static nai_status_t ReadFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t ClearLatchedStatus(int32_t paramCount, int32_t* p_params);
static nai_status_t ClearFifoLatchedStatus(int32_t paramCount, int32_t* p_params);
static const int32_t DEF_PRNT_CHANNEL = 1;
/****** Command Table *******/
enum prnt_basicops_commands
{
PRNT_BASICOP_CMD_RESET,
PRNT_BASICOP_CMD_TERMINATION,
PRNT_BASICOP_CMD_ENABLE,
PRNT_BASICOP_CMD_READ_FIFO,
PRNT_BASICOP_CMD_CLEAR_STATUS,
PRNT_BASICOP_CMD_CLEAR_FIFO_STATUS,
PRNT_BASICOP_CMD_COUNT
};
/****** Command Tables *******/
naiapp_cmdtbl_params_t PRNT_BasicOpMenuCmds[] = {
{"Reset", "Toggle printer reset", PRNT_BASICOP_CMD_RESET, ResetPrinter},
{"Termination", "Set IO Termination", PRNT_BASICOP_CMD_TERMINATION, SetIOTermination},
{"Enable", "Toggle printer Enable/Disable", PRNT_BASICOP_CMD_ENABLE, EnablePrinter},
{"Fifo", "Read and display FIFO data", PRNT_BASICOP_CMD_READ_FIFO, ReadFifo},
{"Clear status", "Clears latched Status", PRNT_BASICOP_CMD_CLEAR_STATUS, ClearLatchedStatus},
{"CF", "Clears Fifo's latched status", PRNT_BASICOP_CMD_CLEAR_FIFO_STATUS, ClearFifoLatchedStatus},
};
/**************************************************************************************************************/
/**
<summary>
The purpose of the PRNT_BasicOps is to illustrate the methods to call in the naibrd library to perform basic
operations with the printer modules for configuration setup and reading rx data from the FIFO.
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 PRNT routines.
- ClearDeviceCfg
- QuerySystemCfg
- DisplayDeviceCfg
- GetBoardSNModCfg
- SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t PRNT_BasicOps(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_PRNT_BasicOps(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_PRNT_BasicOps prompts the user for the card, module (channel is set to 1) to use for the application and calls
Cfg_PRNT_Channel if the card, module, channel is valid for as a printer module.
</summary>
*/
/**************************************************************************************************************/
int32_t Run_PRNT_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
int32_t MaxChannel;
MaxChannel = naibrd_PRNT_GetChannelCount(ModuleID);
if (MaxChannel == 0)
{
printf(" *** Module selection not recognized as PRNT module. ***\n\n");
}
else
{
Cfg_PRNT_Channel(cardIndex, module, ModuleID, MaxChannel);
}
return cardIndex;
}
/**************************************************************************************************************/
/**
<summary>
Cfg_PRNT_Channel handles calling the Display_PRNT_ChannelCfg routine to display the printer's channel configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
static void Cfg_PRNT_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
bool_t bCmdFound = FALSE;
int32_t chan = DEF_PRNT_CHANNEL;
int32_t cmd;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiapp_AppParameters_t prnt_params;
p_naiapp_AppParameters_t prnt_basicops_params = &prnt_params;
prnt_basicops_params->cardIndex = cardIndex;
prnt_basicops_params->module = module;
prnt_basicops_params->channel = chan;
prnt_basicops_params->modId = ModuleID;
prnt_basicops_params->maxChannels = MaxChannel;
while (bContinue)
{
naiapp_utils_LoadParamMenuCommands(PRNT_BASICOP_CMD_COUNT, PRNT_BasicOpMenuCmds);
while (bContinue)
{
Display_PRNT_ChannelCfg(cardIndex, module, chan, ModuleID);
naiapp_display_ParamMenuCommands((int8_t *)"PRNT Basic Operation Menu");
printf("\nType PRNT 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 PRNT_BASICOP_CMD_RESET:
case PRNT_BASICOP_CMD_TERMINATION:
case PRNT_BASICOP_CMD_ENABLE:
case PRNT_BASICOP_CMD_READ_FIFO:
case PRNT_BASICOP_CMD_CLEAR_STATUS:
case PRNT_BASICOP_CMD_CLEAR_FIFO_STATUS:
PRNT_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)prnt_basicops_params);
break;
default:
printf("Invalid command entered\n");
break;
}
}
else
printf("Invalid command entered\n");
}
}
else
bContinue = FALSE;
}
}
}
/**************************************************************************************************************/
/**
<summary>
Display_PRNT_ChannelCfg illustrate the methods to call in the naibrd library to retrieve the configuration states
for basic operation.
</summary>
*/
/**************************************************************************************************************/
static void Display_PRNT_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
nai_prnt_control_t control = (nai_prnt_control_t)0u;
nai_prnt_termination_enable_t terminationEnable = (nai_prnt_termination_enable_t)0u;
nai_prnt_status_t statusRT = (nai_prnt_status_t)0u, statusLT = (nai_prnt_status_t)0u;
nai_prnt_fifo_status_t fifoStatusRT = (nai_prnt_fifo_status_t)0u, fifoStatusLT = (nai_prnt_fifo_status_t)0u;
uint32_t fifoCount = 0u;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
check_status(naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special));
check_status(naibrd_PRNT_GetControl(cardIndex, module, chan, NAI_PRNT_CONTROL_ENABLE | NAI_PRNT_CONTROL_RESET, (uint32_t*)&control));
check_status(naibrd_PRNT_GetTerminationEnable(cardIndex, module, chan, (nai_prnt_termination_enable_t)0xFFFFFFFFu, (uint32_t*)&terminationEnable));
check_status(naibrd_PRNT_GetStatusRaw(cardIndex, module, chan, NAI_PRNT_STATUS_TYPE_REALTIME, &statusRT));
check_status(naibrd_PRNT_GetStatusRaw(cardIndex, module, chan, NAI_PRNT_STATUS_TYPE_LATCHED, &statusLT));
check_status(naibrd_PRNT_GetRxFIFOCount(cardIndex, module, chan, &fifoCount));
check_status(naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, chan, NAI_PRNT_STATUS_TYPE_REALTIME, &fifoStatusRT));
check_status(naibrd_PRNT_GetFIFOStatusRaw(cardIndex, module, chan, NAI_PRNT_STATUS_TYPE_LATCHED, &fifoStatusLT));
printf("\r\n\r\n");
printf("Channel ===Control=== =Termination= ==Status(R/L)== =FIFO Count= ==============FIFO Status(R/L)============\r\n");
printf(" ENABLE RESET DATA_AVAILABLE EMPTY ALMST_EMPTY ALMST_FULL FULL OVERFLOW\r\n");
printf("---------------------------------------------------------------------------------------------------------------\r\n");
printf(" %2i %u %u 0x%04X (%u/%u) %4u (%u/%u) (%u/%u) (%u/%u) (%u/%u) (%u/%u)\r\n",
chan, 0 != (control & NAI_PRNT_CONTROL_ENABLE), 0 != (control & NAI_PRNT_CONTROL_RESET), terminationEnable,
0 != (statusRT & NAI_PRNT_STATUS_DATA_AVAILABLE), 0 != (statusLT & NAI_PRNT_STATUS_DATA_AVAILABLE), fifoCount,
0 != (fifoStatusRT & NAI_PRNT_FIFO_STATUS_EMPTY), 0 != (fifoStatusLT & NAI_PRNT_FIFO_STATUS_EMPTY),
0 != (fifoStatusRT & NAI_PRNT_FIFO_STATUS_ALMOST_EMPTY), 0 != (fifoStatusLT & NAI_PRNT_FIFO_STATUS_ALMOST_EMPTY),
0 != (fifoStatusRT & NAI_PRNT_FIFO_STATUS_ALMOST_FULL), 0 != (fifoStatusLT & NAI_PRNT_FIFO_STATUS_ALMOST_FULL),
0 != (fifoStatusRT & NAI_PRNT_FIFO_STATUS_FULL), 0 != (fifoStatusLT & NAI_PRNT_FIFO_STATUS_FULL),
0 != (fifoStatusRT & NAI_PRNT_FIFO_STATUS_OVERFLOW), 0 != (fifoStatusLT & NAI_PRNT_FIFO_STATUS_OVERFLOW) );
}
/**************************************************************************************************************/
/**
<summary>
ResetPrinter illustrate the methods to call in the naibrd library to reset the printer.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ResetPrinter(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
uint32_t controlData = 0;
nai_status_t status = NAI_ERROR_UNKNOWN;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
status = check_status(naibrd_PRNT_GetControl(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
NAI_PRNT_CONTROL_RESET, &controlData));
if (status == NAI_SUCCESS)
{
status = check_status(naibrd_PRNT_SetControl(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
NAI_PRNT_CONTROL_RESET, ~controlData));
}
return status;
}
/**************************************************************************************************************/
/**
<summary>
SetIOTermination illustrate the methods to call in the naibrd library to set the termination resistors on the
printer's I/O lines.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t SetIOTermination(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
nai_prnt_termination_enable_t terminationBits = (nai_prnt_termination_enable_t)0u;
uint32_t terminationBitValuesSet = 0;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\r\n\r\nTermination Bit values:\r\n");
printf("NAI_PRNT_TERM_ENABLE_D0 = 0x00000001\r\n");
printf("NAI_PRNT_TERM_ENABLE_D1 = 0x00000002\r\n");
printf("NAI_PRNT_TERM_ENABLE_D2 = 0x00000004\r\n");
printf("NAI_PRNT_TERM_ENABLE_D3 = 0x00000008\r\n");
printf("NAI_PRNT_TERM_ENABLE_D4 = 0x00000010\r\n");
printf("NAI_PRNT_TERM_ENABLE_D5 = 0x00000020\r\n");
printf("NAI_PRNT_TERM_ENABLE_D6 = 0x00000040\r\n");
printf("NAI_PRNT_TERM_ENABLE_PARITY = 0x00000080\r\n");
printf("NAI_PRNT_TERM_ENABLE_STROBE = 0x00000100\r\n");
printf("NAI_PRNT_TERM_ENABLE_DEMAND = 0x00000200\r\n");
printf("NAI_PRNT_TERM_ENABLE_READY = 0x00000400\r\n");
printf("NAI_PRNT_TERM_ENABLE_STATUS = 0x00000800\r\n");
do
{
printf("\r\nEnter Termination bit(s) to modify in Hex (0x0001..0x0FFF): 0x");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
terminationBits = naiapp_utils_HexStrToDecUInt32(inputBuffer);
}
}
} while (!bQuit && inputResponseCnt == 0);
do
{
printf("\r\nEnter Termination bit value(s) in Hex (0x0000..0x0FFF): 0x");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
terminationBitValuesSet = naiapp_utils_HexStrToDecUInt32(inputBuffer);
}
}
} while (!bQuit && inputResponseCnt == 0);
printf("Setting Termination bit(s) 0x%08X to 0x%08X\r\n", terminationBits, terminationBitValuesSet);
check_status(naibrd_PRNT_SetTerminationEnable(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
terminationBits, terminationBitValuesSet));
return NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
EnablePrinter handles the user request to enable/disable the printer.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t EnablePrinter(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
uint32_t controlData;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
check_status(naibrd_PRNT_GetControl(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
NAI_PRNT_CONTROL_ENABLE, &controlData));
return check_status(naibrd_PRNT_SetControl(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
NAI_PRNT_CONTROL_ENABLE, ~controlData));
}
/**************************************************************************************************************/
/**
<summary>
ReadFifo handles the user request to read the rx data from the fifo and display it.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ReadFifo(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
int32_t bufferIndex = 0;
uint32_t rxFifoData[NAI_PRNT_FIFO_SIZE];
uint32_t countRemaining = 0;
uint32_t readCount = 0;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
for (bufferIndex = 0; bufferIndex < NAI_PRNT_FIFO_SIZE; bufferIndex++)
rxFifoData[bufferIndex] = 0;
check_status(naibrd_PRNT_ReadRxFIFO(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel, NAI_PRNT_FIFO_SIZE,
&countRemaining, rxFifoData, &readCount));
printf("%u items read from the FIFO, %u items remain\r\n", readCount, countRemaining);
for (bufferIndex = 0; bufferIndex < (int32_t)readCount; bufferIndex++)
{
printf("%2u) 0x%08X\r\n", bufferIndex + 1, rxFifoData[bufferIndex]);
}
return NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
ClearLatchedStatus illustrate the methods to call in the naibrd library to clear the latched status states.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ClearLatchedStatus(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
nai_prnt_status_t prntStatusBits = (nai_prnt_status_t)0;
nai_status_t status = NAI_ERROR_INVALID_VALUE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\r\n\r\nStatus Bit values:\r\n");
printf("NAI_PRNT_STATUS_DATA_AVAILABLE = 0x00000001\r\n");
do
{
printf("\r\nEnter Status bit(s) to clear in Hex (0x0001..0x0001): 0x");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
prntStatusBits = (nai_prnt_status_t)naiapp_utils_HexStrToDecUInt32(inputBuffer);
}
}
} while (!bQuit && (inputResponseCnt == 0));
if (!bQuit && (inputResponseCnt > 0))
{
status = check_status(naibrd_PRNT_ClearStatus(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
prntStatusBits));
}
return status;
}
/**************************************************************************************************************/
/**
<summary>
ClearFifoLatchedStatus illustrate the methods to call in the naibrd library to clear the fifo latched status states.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ClearFifoLatchedStatus(int32_t paramCount, int32_t* p_params)
{
p_naiapp_AppParameters_t p_prnt_params = (p_naiapp_AppParameters_t)p_params;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
nai_prnt_fifo_status_t fifoStatusBits = (nai_prnt_fifo_status_t)0u;
nai_status_t status = NAI_ERROR_INVALID_VALUE;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
printf("\r\n\r\nFIFO Status Bit values:\r\n");
printf("NAI_PRNT_FIFO_STATUS_EMPTY = 0x00000001\r\n");
printf("NAI_PRNT_FIFO_STATUS_ALMOST_EMPTY = 0x00000002\r\n");
printf("NAI_PRNT_FIFO_STATUS_ALMOST_FULL = 0x00000004\r\n");
printf("NAI_PRNT_FIFO_STATUS_FULL = 0x00000008\r\n");
printf("NAI_PRNT_FIFO_STATUS_OVERFLOW = 0x00000010\r\n");
do
{
printf("\r\nEnter FIFO Status bit(s) to clear in Hex (0x0001..0x001F): 0x");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
fifoStatusBits = (nai_prnt_fifo_status_t)naiapp_utils_HexStrToDecUInt32(inputBuffer);
}
}
} while (!bQuit && (inputResponseCnt == 0));
if (!bQuit && (inputResponseCnt == 0))
{
status = check_status(naibrd_PRNT_ClearFIFOStatus(p_prnt_params->cardIndex, p_prnt_params->module, p_prnt_params->channel,
fifoStatusBits));
}
return status;
}