M1553 RT HBuff
Edit this on GitLab
M1553 RT HBuff Sample Application (SSK 1.x)
Overview
The M1553 RT HBuff sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT) with host buffer-based message management using the NAI Software Support Kit (SSK 1.x). Unlike a Bus Controller (BC), which initiates transfers on the bus, an RT passively waits for a BC to send commands before responding. This sample shows how to set up that passive responder role, including double-buffered Tx data (active/inactive buffer switching via naibrd_1553_RtTxDataBlockSwap()), configurable Rx buffering (single, double, or circular), and host buffer-based message decoding with stack and host buffer loss tracking.
The key host buffer API calls demonstrated are:
-
naibrd_1553_RtStkToHbuf32()— copies messages from the RT stack to the host buffer. -
naibrd_1553_RTGetHBufMsgCount()— returns the number of messages waiting in the host buffer. -
naibrd_1553_RtGetHBufMsgDecoded()— retrieves and decodes the next message, reporting any stack or host buffer message losses.
This sample supports the following 1553 module types:
-
4-channel modules: FT0 through FT9 and FTA through FTF
-
2-channel 1760 modules: FTJ and FTK
-
Combination modules: CM1, CM5, and CM8
For detailed register maps and module-specific behavior, refer to the FTA-FTF Manual and FTJ-FTK Manual.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a supported 1553 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 M1553_RT_HBuff executable from your build output directory. On startup the application looks for a configuration file (default_1553_RT_HBuff.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, the application walks you through RT-specific settings (channel, RT address, subaddress, Rx buffer type) and then enters a timed monitoring loop that processes messages from the bus.
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 1553. |
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_1553_RT_HBuff.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 adapt to the specific 1553 variant installed. -
If a valid module is found, call
GetRTHBufDecodedMsgs()to begin RT configuration and message processing.
#if defined (__VXWORKS__)
int32_t M1553_RT_HBuff(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))
{
GetRTHBufDecodedMsgs(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
The program entry point is main() on most platforms or M1553_RT_HBuff() on VxWorks. After the board connection and module selection described above, the application calls GetRTHBufDecodedMsgs(), which handles all RT-specific configuration and message processing.
Module Detection
The module ID returned by naibrd_GetModuleID() determines the channel count and capabilities of the installed module. The 1553 utility functions used in this sample detect the module variant internally:
-
IsFTx1553()— returns true for standard 1553 modules (FT0-FT9, FTA-FTF), which provide 4 channels. -
IsFTx1760()— returns true for MIL-STD-1760 modules (FTJ, FTK), which provide 2 channels.
These checks are performed inside the utility functions called during the user input flow, so the application automatically adapts its channel numbering and defaults to the installed hardware.
User Input Flow
Once inside GetRTHBufDecodedMsgs(), the application collects RT operating parameters through a series of utility functions. Each function presents a prompt, accepts user input, and falls back to a compiled-in default if the user presses Enter without typing a value:
-
Get1553RTCfg()— prompts for the 1553 channel number and RT address. It uses the module ID to determine valid channel ranges (4 channels for standard 1553 modules, 2 for 1760 modules). The defaults are channel 1 and RT address 1. -
Get1553Address()— prompts for the subaddress to legalize for Tx and Rx traffic. Valid subaddresses are 1 through 31. The default is subaddress 2. -
Get1553LogicalDevNum()— prompts for a logical device number. The logical device number is a software handle that the naibrd library uses to associate a specific card/module/channel combination with subsequent API calls. The default is device 1. -
Get1553RTAddressSource()— asks whether to set the RT address in software or use the hardware address pins. When software addressing is selected, the application writes to the auxiliary registers to enable software RT address control and then callsnaibrd_1553_RtSetAddress()to program the address. When hardware addressing is selected, the RT address is read from the module’s physical address pins. -
Get1553RxBufferType()— prompts the user to select the Rx data block buffering mode: single buffer, double buffer, or circular buffer. Double buffering (the default) allows the RT to receive a new message into one buffer while the application reads the previous message from the other, reducing the chance of data loss under high message rates.
|
Note
|
Because the RT operates as a responder rather than an initiator, the application enters a timed monitoring loop after configuration is complete. During this loop the RT waits for BC commands, periodically updates Tx buffer contents, copies stack messages to the host buffer, and decodes any new messages. The user specifies the loop duration in seconds before each run. |
RT Subaddress Architecture
BC vs. RT Roles
BC initiates all communication on the 1553 bus. RT listens on a specific address and responds when BC sends a command targeting its address and subaddress. RT doesn’t decide when to communicate — it reacts.
RT Address
The RT address identifies this terminal on the bus (0–30, 31 = broadcast). It must be unique per bus. The address can be set from hardware pins or software (covered in Section 4).
Subaddresses
Within an RT, subaddresses 1–30 organize data into logical channels. Subaddresses 0 and 31 are reserved for mode codes. Each subaddress can be mapped for Rx (BC→RT), Tx (RT→BC), or both.
Data Blocks
Data blocks are memory buffers on the 1553 module mapped to subaddresses. When the BC sends data to a subaddress, the hardware writes to the mapped Rx data block. When the BC requests data from a subaddress, the hardware reads from the mapped Tx data block. Data blocks are created with naibrd_1553_RtDataBlockCreate() and mapped with naibrd_1553_RtDataBlockMapToSubaddress().
RT Address Configuration
The RT address can be set from two sources: software control or hardware address pins. The application calls Get1553RTAddressSource() to let the user choose, then executes the corresponding code path. Both paths write to auxiliary register 0x2 but with different bit masks.
Software Addressing
Set the RTAD_SW_EN and RT_ADR_LAT bits (value 0x0018) in auxiliary register 0x2 via naibrd_1553_WriteAuxReg(), then program the desired address with naibrd_1553_RtSetAddress(). This gives the application full control over the RT address. Software addressing is typical for development, test, and Ethernet-connected boards where the address needs to change without rewiring.
Hardware Pin Addressing
Set only the RT_ADR_LAT bit (value 0x0008) in auxiliary register 0x2 via naibrd_1553_WriteAuxReg(). The RT address is read from the module’s external address pins. The application does not call naibrd_1553_RtSetAddress() in this mode. Hardware pin addressing is required in some MIL-STD-1760 installations where the platform wiring determines the RT address.
Source Code
The following excerpt from the sample (lines 172-190) shows both code paths:
if (bSoftwareRTAddr)
{
/* Set RTAD_SW_EN and RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0018);
/* Set RT address */
swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtSetAddress %d", swResult);
return bQuit;
}
}
else
{
/* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
}
For complete register bit definitions, refer to the FTA-FTF Manual.
|
Important
|
|
Buffer Types and Data Block Configuration
This section covers how the sample creates and maps data blocks for Rx and Tx traffic on the configured subaddress. The Rx side offers three buffer types with different trade-offs; the Tx side uses an explicit two-block swap pattern to avoid sending stale data.
Rx Buffer Types
The user selects the Rx buffer type at startup via Get1553RxBufferType(). The choice determines how the hardware manages incoming data for the mapped subaddress.
Single (NAI_1553_RT_DATABLOCK_SINGLE_32, 32 words) — the simplest option. One 32-word buffer holds the most recent message. If the BC sends a new message while the host is reading, the host may see partially-updated data. Suitable for low-rate subaddresses where the host can always read between messages.
Double (NAI_1553_RT_DATABLOCK_DOUBLE, 64 words = 2 x 32) — the hardware maintains two buffers (A and B) and automatically swaps between them on each message. While the BC writes to one buffer, the host reads from the other. This prevents data tearing and is the default mode in the sample.
Circular — a ring buffer for high-rate traffic. Messages are queued sequentially so that every message is captured, even when the host cannot read them one-by-one in real time. Use circular buffering when every message must be recorded and the BC message rate may exceed the host read rate.
Rx Data Block Creation and Mapping
After the buffer type is selected, the sample creates a single Rx data block and maps it to the chosen subaddress:
/* Create a Rx Buffer data block and map to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_RX, nDataBlockType, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_RX, sa, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
naibrd_1553_RtDataBlockCreate() allocates the data block on the module. DevNum is the logical device handle, DATA_BLOCK_ID_RX is a user-defined block identifier, and nDataBlockType is the buffer type selected at startup. The NULL and 0 arguments are for an optional user-supplied buffer pointer and size (not used here — the library allocates internally).
naibrd_1553_RtDataBlockMapToSubaddress() binds the block to a subaddress. sa is the subaddress number, NAI_1553_RT_MESSAGE_TYPE_RX marks this mapping as receive, and the final argument (1) is the legalization flag — setting it to 1 legalizes the subaddress so the RT will respond to BC commands targeting it.
Tx Double-Buffering Pattern
For transmit, the sample creates two single-type data blocks (DATA_BLOCK_ID_TX1 and DATA_BLOCK_ID_TX2) and maps the first one as the active Tx block:
/* Create two Tx Buffer data blocks and map the first to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX1, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_TX1, sa, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
if (swResult < 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
currDataBlock = DATA_BLOCK_ID_TX1;
TX1 is mapped as the active block and currDataBlock tracks which block the BC is currently reading from. The application writes new data into the inactive block (TX2 initially), then calls naibrd_1553_RtTxDataBlockSwap() to atomically swap the active and inactive blocks. This ensures the BC always reads a complete, consistent data set — it never sees a half-written buffer.
|
Note
|
Rx double-buffering is handled automatically by the hardware when you create a single DOUBLE-type block. Tx double-buffering is done explicitly in software using two SINGLE-type blocks and the naibrd_1553_RtTxDataBlockSwap() API.
|
|
Important
|
|
Two-Stage Message Path
Why Two Stages?
RT hardware receives messages at bus speed (1 Mbps) and stores them in an internal stack. The host application, however, runs at its own pace. The host buffer provides a larger, CPU-accessible staging area that decouples hardware reception from application processing. This two-stage design ensures that bursty bus traffic does not immediately overwhelm the application’s read loop.
Stage 1: RT Stack
The RT stack is a hardware-managed FIFO that captures raw messages as they arrive from the bus. Its capacity is limited. If the stack fills before the application transfers messages out, the overflow is counted in the dwStkLost field. The stack is internal to the 1553 module and is not directly addressable by the host CPU — messages must be explicitly copied out.
Stage 2: Host Buffer
The application calls naibrd_1553_RtStkToHbuf32() to copy messages from the RT stack into the host buffer. The host buffer can hold up to 131,072 words, installed via naibrd_1553_RtHbuffInstall(DevNum, NAI_1553_MAX_SIZE_OF_HOST_BUFFER). If the host buffer fills before the application reads messages out, the overflow is counted in the dwHBufLost field.
Reading Messages
naibrd_1553_RTGetHBufMsgCount() checks how many messages are available in the host buffer. naibrd_1553_RtGetHBufMsgDecoded() retrieves the next message and decodes it. To remove messages after reading, pass NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE as the location parameter, which advances the read pointer and frees the slot for new data.
Loss Tracking
Both dwStkLost and dwHBufLost are returned by the decode function. A nonzero value in either field means the application is not keeping up with incoming traffic. Possible solutions include increasing the polling rate, increasing the host buffer size, or reducing the message rate on the bus.
Message Processing Loop
The ProcessMessages() function is the core runtime loop. It runs for a user-specified duration (default 5 seconds), polling the host buffer every 10 ms (nai_msDelay(10)) for new messages. On each iteration it transfers messages from the RT stack to the host buffer, checks the message count, decodes any available messages, and periodically updates the Tx data block contents.
Tx Buffer Updates
Every 1 second, the loop calls UpdateTxDataBlock() to refresh the Tx data. UpdateTxDataBlock() determines which data block is currently inactive (whichever the BC is not reading from), calls UpdateTxBuffer() to write incrementing data into it, then calls naibrd_1553_RtTxDataBlockSwap() to atomically make the updated block active.
static int32_t UpdateTxDataBlock(uint16_t DevNum, uint8_t Subaddress)
{
/* Update Data in TX Data Block */
if (currDataBlock == DATA_BLOCK_ID_TX1)
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX2);
/* Change data pointer to block 2 */
naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX2, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX2;
}
else
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX1);
/* Change data pointer to block 1 */
naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX1, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX1;
}
return 0;
}
UpdateTxBuffer() increments a static 32-word array and writes it to the specified data block with naibrd_1553_RtDataBlockWrite():
static int32_t UpdateTxBuffer(uint16_t DevNum, uint16_t nDataBlkID)
{
static uint16_t wBuffer[32] = { 0x0000 };
uint16_t i = 0x0000;
uint32_t swResult;
/* Increment Tx buffer data */
for (i = 0; i < 32; i++)
{
wBuffer[i] += 1;
}
/* Write new data to Tx buffer */
swResult = naibrd_1553_RtDataBlockWrite(DevNum, nDataBlkID, wBuffer, RTBC_WORDCNT, 0);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtDataBlockWrite %d\n\n", swResult);
return 0;
}
else
{
printf("New data written to Tx Buffer\n\n");
}
return 1;
}
Stack-to-Host Transfer
Each iteration calls naibrd_1553_RtStkToHbuf32(DevNum) (line 362) to copy any new messages from the RT hardware stack into the host buffer. This must be called frequently enough to prevent the stack from overflowing.
Message Count
After the transfer, naibrd_1553_RTGetHBufMsgCount(DevNum) (line 370) returns the number of decoded messages waiting in the host buffer. The loop proceeds to decode only when at least one message is available.
Message Decode
When messages are available, the loop calls naibrd_1553_RtGetHBufMsgDecoded(DevNum, &sMsg, &dwMsgCount, &dwStkLost, &dwHBufLost, NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE) (line 375) to retrieve and decode the next message. The NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE flag advances the read pointer and frees the slot after reading.
Message Type Discrimination
The command word’s TR bit (bit 0x0400) distinguishes Rx from Tx messages. When the bit is 0, the BC sent data to the RT (Rx). When the bit is 1, the BC requested data from the RT (Tx). The sample prints different fields depending on direction:
if ((sMsg.wCommandWord1 & 0x0400) != 0x0400) /* If this is a Rx message */
{
printf("Rx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("Data:");
for (i = 0; i < sMsg.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", sMsg.waData[i]);
}
printf("count: %d\n", count++);
printf("\n\n");
}
else
{
printf("Tx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("count: %d\n", count++);
printf("\n\n");
}
For Rx messages, the decoded output includes the full data payload (waData[]). For Tx messages, only the header fields are displayed since the data was written by the RT itself.
Loss Tracking
If either dwStkLost or dwHBufLost is nonzero after decoding, the loop prints the total number of lost messages (lines 383-386). Stack losses indicate messages were overwritten in the hardware FIFO before RtStkToHbuf32() could transfer them. Host buffer losses indicate the host buffer filled before the application could read messages out.
Decoded Fields
Each decoded message (naiDecodedMessageStructure) contains:
-
Block Status (
wBlockStatus) — hardware status flags for the message transfer. -
Time Tag (
wTimeTag) — hardware timestamp of when the message was received. -
Command Word (
wCommandWord1) — the 1553 command word containing the RT address, subaddress, TR bit, and word count. -
Data Word Count (
wDataWordCount) — number of data words in the message. -
Payload (
waData[]) — the actual data words (displayed for Rx messages only).
|
Important
|
|
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.
Diagnosing RT Communication Issues
When an RT doesn’t respond to BC commands or messages are missing, verify three things:
-
RT address matches the BC’s target. The BC sends commands to a specific RT address. If the RT’s address (set via software or hardware pins) doesn’t match, the RT will ignore the command entirely.
-
Subaddress is legalized. Only legalized subaddresses respond to BC commands. If you mapped a data block to a subaddress but didn’t set
bIsSubaddressLegalizationRequested = 1, the RT will not acknowledge commands on that subaddress. -
RT is started.
naibrd_1553_RtStart()must be called after all configuration. Until the RT is started, it will not respond to any bus traffic.
If the RT responds but data is wrong or missing, check the host buffer message path: call naibrd_1553_RtStkToHbuf32() frequently enough and monitor the loss counters (dwStkLost, dwHBufLost). Consult the FTA-FTF Manual for RT status and block status word definitions.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, missing configuration file, network issue |
Verify hardware and configuration file. If file doesn’t exist, configure and save from board menu. |
Module not recognized as 1553 |
Selected module is not FT-series or CM with 1553 |
Verify module type at the selected slot. |
Device open or initialization failure |
Wrong card/module/channel, or device already in use |
Verify parameters. Close other applications using this channel. |
RT address mismatch |
RT address doesn’t match what BC is targeting |
Confirm address set via |
RT address source conflict |
Software address set but hardware pin mode active, or vice versa |
Match |
Subaddress not legalized |
Data block mapped without legalization flag |
Set |
No messages appearing |
RT not started, subaddress not legalized, or BC not sending to this RT/subaddress |
Verify |
Data block creation or mapping failure |
Invalid block type, ID, or subaddress out of range |
Verify block type constants and subaddress range (1-30 for data, 0/31 for mode codes). |
Tx data stale from BC perspective |
|
Always swap after writing to the inactive block. Verify |
Messages lost in RT stack |
Application not calling |
Increase polling rate or reduce loop delay. |
Messages lost in host buffer |
Host buffer full before messages are read |
Increase buffer size at install time or process messages faster. |
Rx data tearing |
Wrong buffer type for message rate — single buffer under load |
Switch to double-buffered ( |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — M1553_RT_HBuff.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.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"
/* Common 1553 Sample Program include files */
#include "nai_1553_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_1553.h"
static const int8_t *CONFIG_FILE = (int8_t *)"default_1553_RT_HBuff.txt";
/* Function prototypes */
static bool_t GetRTHBufDecodedMsgs(int32_t cardIndex, int32_t module, uint32_t modid);
static int32_t UpdateTxDataBlock(uint16_t DevNum, uint8_t Subaddress);
static int32_t UpdateTxBuffer(uint16_t DevNum, uint16_t nDataBlkID);
static int32_t ProcessMessages(uint16_t DevNum, uint8_t Subaddress, int32_t duration);
static const uint16_t DATA_BLOCK_ID_TX1 = 1;
static const uint16_t DATA_BLOCK_ID_TX2 = 2;
static const uint16_t DATA_BLOCK_ID_RX = 3;
static const int32_t DEF_RT_CHANNEL = 1;
static const int16_t DEF_RT_DEV_NUM = 1;
static const uint8_t DEF_RT_ADDRESS = 1;
static const uint8_t DEF_RT_SUBADDR = 2;
static const uint16_t DEF_RT_RX_BUF_TYPE = NAI_1553_RT_DATABLOCK_DOUBLE;
static const uint16_t RTBC_WORDCNT = 32;
/* Global Variables */
static int32_t currDataBlock;
/**************************************************************************************************************/
/**
<summary>
The purpose of the M1553_RT_HBuff is to illustrate the methods to call in the naibrd library to configure the 1553 channel as a
Remote Terminal, utilize Rt Host Buffers, legalize Subaddress 2 for both Tx and Rx, and set it up to receive data
using an Rx double buffer and transmit data from two alternating Tx buffers (active and inactive). If a Rx message
is received, the received data will be displayed. If a Rx message is received, the received data will be data will be displayed.
If a Tx message is received, the data in the active tx buffer will be copied over from the Rt stack to the Host Buffer, and the data will be
sent to the bus. While the RT is running, Tx buffer data will be updated periodically via the Rt stack to Host Buffer copy operation. The
use of the following Host Buffer functions will be demonstrated:
naibrd_1553_RtStkToHbuf32
naibrd_1553_RTGetHBufMsgCount
naibrd_1553_RtGetHBufMsgDecoded
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 1553 routines.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t M1553_RT_HBuff(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))
{
GetRTHBufDecodedMsgs(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;
}
static bool_t GetRTHBufDecodedMsgs(int32_t cardIndex, int32_t module, uint32_t modid)
{
/* Variables */
bool_t bQuit = FALSE;
int32_t rtchan;
uint8_t rtaddr;
uint8_t sa = DEF_RT_SUBADDR;
int16_t DevNum = 0;
int32_t swResult;
uint16_t nDataBlockType = 0;
bool_t bContinue = TRUE;
int32_t duration;
bool_t bSoftwareRTAddr;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Get Card, Module, Channel Numbers and Open a Handle */
bQuit = Get1553RTCfg(modid, DEF_RT_CHANNEL, DEF_RT_ADDRESS, &rtchan, &rtaddr);
if (bQuit)
{
return bQuit;
}
printf("Enter Subaddress\n");
bQuit = Get1553Address(31, DEF_RT_SUBADDR, &sa);
/* Get Logical Device # */
bQuit = Get1553LogicalDevNum(DEF_RT_DEV_NUM, &DevNum);
if (bQuit)
{
return bQuit;
}
/* Associate Card, Module and Channel Numbers with the Logical Device # */
swResult = naibrd_1553_Open(cardIndex, module, rtchan, DevNum);
if (swResult)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Open %d", swResult);
return bQuit;
}
/* Initialize Device */
swResult = naibrd_1553_Initialize(DevNum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_RT, 0, 0, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Initialize %d", swResult);
return bQuit;
}
/* Get RT Address Source from user */
bQuit = Get1553RTAddressSource(TRUE, &bSoftwareRTAddr);
if (bQuit)
{
return bQuit;
}
if (bSoftwareRTAddr)
{
/* Set RTAD_SW_EN and RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0018);
/* Set RT address */
swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtSetAddress %d", swResult);
return bQuit;
}
}
else
{
/* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
}
if (modid == NAI_MODULE_ID_FT8)
{
/* Simplex Enable (for internal NAI testing only, do not enable) */
//naibrd_1553_WriteAuxReg(DevNum, 0x3, 0x4000);
//naibrd_1553_WriteAuxReg(DevNum, 0xF, 0x1);
}
/* Select Single Buffer, Double Buffer or Circular Buffer for Rx Messages */
bQuit = Get1553RxBufferType(DEF_RT_RX_BUF_TYPE, &nDataBlockType);
if (bQuit)
{
return bQuit;
}
/* Create a Rx Buffer data block and map to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_RX, nDataBlockType, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_RX, sa, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
/* Create two Tx Buffer data blocks and map the first to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX1, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_TX1, sa, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
if (swResult < 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
currDataBlock = DATA_BLOCK_ID_TX1;
while (bContinue)
{
printf("\nType duration (in seconds) to run RT or %c to quit (default: 5) : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
duration = 5;
if (inputResponseCnt > 0)
{
duration = (int)atol((const char*)inputBuffer);
}
/* Create Host Buffer */
swResult = naibrd_1553_RtHbuffInstall(DevNum, NAI_1553_MAX_SIZE_OF_HOST_BUFFER);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtHbuffInstall %d", swResult);
return bQuit;
}
/* Start RT */
swResult = naibrd_1553_RtStart(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStart %d", swResult);
return bQuit;
}
/* Process New Messages */
ProcessMessages(DevNum, sa, duration);
/* Stop RT */
swResult = naibrd_1553_RtStop(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStop %d", swResult);
return bQuit;
}
}
else
bContinue = FALSE;
}
swResult = naibrd_1553_RtHbuffUnInstall(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtHbuffUnInstall %d", swResult);
return bQuit;
}
/* Free 1553 Device */
swResult = naibrd_1553_Free(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Free %d", swResult);
return bQuit;
}
return bQuit;
}
static int32_t UpdateTxDataBlock(uint16_t DevNum, uint8_t Subaddress)
{
/* Update Data in TX Data Block */
if (currDataBlock == DATA_BLOCK_ID_TX1)
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX2);
/* Change data pointer to block 2 */
naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX2, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX2;
}
else
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX1);
/* Change data pointer to block 1 */
naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX1, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX1;
}
return 0;
}
static int ProcessMessages(uint16_t DevNum, uint8_t Subaddress, int32_t duration)
{
time_t end, period;
uint32_t swResult;
int32_t i;
uint32_t dwStkLost = 0;
uint32_t dwHBufLost = 0;
uint32_t dwMsgCount = 0;
uint32_t dwMsgCountGet = 0;
uint32_t dwCurCount = 0;
int32_t count = 0;
naiDecodedMessageStructure sMsg;
end = time(NULL) + duration;
period = time(NULL) + 1;
while (time(NULL) < end)
{
/* Update Tx Data Block periodically */
if (time(NULL) > period)
{
UpdateTxDataBlock(DevNum, Subaddress);
period = time(NULL) + 1;
}
/* Update message count */
swResult = naibrd_1553_RtStkToHbuf32(DevNum);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtStkToHbuf32 %d\n\n", swResult);
return 0;
}
/* get message count */
dwMsgCountGet = naibrd_1553_RTGetHBufMsgCount(DevNum);
if (dwMsgCountGet >= 1)
{
/* Decode Raw Message */
swResult = naibrd_1553_RtGetHBufMsgDecoded(DevNum, &sMsg, &dwMsgCount, &dwStkLost, &dwHBufLost, NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtGetHBufMsgDecoded %d\n\n", swResult);
return 0;
}
/* Message Lost */
if ((dwStkLost > 0) || (dwHBufLost > 0))
{
printf("Number of msgs lost %d\n", (int)(dwStkLost + dwHBufLost));
}
/* Message Found */
if (dwMsgCount)
{
++dwCurCount;
if ((sMsg.wCommandWord1 & 0x0400) != 0x0400) /* If this is a Rx message */
{
printf("Rx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("Data:");
for (i = 0; i < sMsg.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", sMsg.waData[i]);
}
printf("count: %d\n", count++);
printf("\n\n");
}
else
{
printf("Tx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("count: %d\n", count++);
printf("\n\n");
}
}
}
nai_msDelay(10);
}
return 1;
}
static int32_t UpdateTxBuffer(uint16_t DevNum, uint16_t nDataBlkID)
{
static uint16_t wBuffer[32] = { 0x0000 };
uint16_t i = 0x0000;
uint32_t swResult;
/* Increment Tx buffer data */
for (i = 0; i < 32; i++)
{
wBuffer[i] += 1;
}
/* Write new data to Tx buffer */
swResult = naibrd_1553_RtDataBlockWrite(DevNum, nDataBlkID, wBuffer, RTBC_WORDCNT, 0);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtDataBlockWrite %d\n\n", swResult);
return 0;
}
else
{
printf("New data written to Tx Buffer\n\n");
}
return 1;
}
Full Source — nai_1553_utils.c (SSK 1.x)
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
#include "nai_1553_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_1553.h"
#include "maps/nai_map_1553.h"
static int32_t g_MenuCmdCnt = 0;
bool_t Get1553Address(int32_t maxaddress, int8_t defaddress, uint8_t *address)
{
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (maxaddress > 1)
{
while (bContinue)
{
printf("\nEnter address [default=%d]: ", defaddress);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
*address = defaddress;
else
*address = (uint8_t)atol((const char*)inputBuffer);
if ((*address < 0) || (*address > maxaddress))
printf("ERROR: Invalid address value.\n\n");
else
bContinue = FALSE;
}
}
}
else
*address = 0;
return bQuit;
}
bool_t Get1553MTCfg(uint32_t modid, int32_t defchan, int32_t *rtchan )
{
bool_t bQuit = FALSE;
int32_t MaxChannel;
if (IsSUMMIT1553(modid))
{
/* Get the number of 1553 channels on the module */
MaxChannel = 2;
/* Get the RT channel */
printf("\nRemote Terminal Setup\n");
printf("---------------------\n");
printf("1553 RT Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, rtchan);
}
else if (IsFTx1553(modid))
{
MaxChannel = 4;
/* Get the RT channel */
printf("\nRemote Terminal Setup\n");
printf("---------------------\n");
printf("1553 RT Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, rtchan);
}
else
printf("ERROR: Module selected does not support 1553 Functionality\n");
return bQuit;
}
bool_t Get1553RTCfg(uint32_t modid, int32_t defchan, uint8_t defaddr, int32_t *rtchan, uint8_t *rtaddr )
{
bool_t bQuit = FALSE;
int32_t MaxChannel;
if (IsSUMMIT1553(modid))
{
/* Get the number of 1553 channels on the module */
MaxChannel = 2;
/* Get the RT channel */
printf("\nRemote Terminal Setup\n");
printf("---------------------\n");
printf("1553 RT Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, rtchan);
if (!bQuit)
{
printf("1553 RT Address Selection:");
bQuit = Get1553Address(31, defaddr, rtaddr);
}
}
else if (IsFTx1553(modid))
{
MaxChannel = 4;
/* Get the RT channel */
printf("\nRemote Terminal Setup\n");
printf("---------------------\n");
printf("1553 RT Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, rtchan);
if (!bQuit)
{
printf("1553 RT Address Selection:");
bQuit = Get1553Address(31, defaddr, rtaddr);
}
}
else if (IsFTx1760(modid))
{
MaxChannel = 4;
/* Get the RT channel */
printf("\nRemote Terminal Setup\n");
printf("---------------------\n");
printf("1760 RT Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, rtchan);
if (!bQuit)
{
printf("1760 RT Address Selection:");
bQuit = Get1553Address(31, defaddr, rtaddr);
}
}
else
printf("ERROR: Module selected does not support 1553 Functionality\n");
return bQuit;
}
bool_t Get1553BCCfg(uint32_t modid, int32_t defchan, int32_t *bcchan )
{
bool_t bQuit = FALSE;
int32_t MaxChannel;
if (IsSUMMIT1553(modid))
{
MaxChannel = 2;
/* Get the BC channel */
printf("\nBus Controller Setup:\n");
printf("---------------------\n");
printf("1553 BC Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, bcchan);
}
else if (IsFTx1553(modid))
{
MaxChannel = 4;
/* Get the BC channel */
printf("\nBus Controller Setup:\n");
printf("---------------------\n");
printf("1553 BC Channel Selection:");
bQuit = naiapp_query_ChannelNumber(MaxChannel, defchan, bcchan);
}
else
printf("ERROR: Module selected does not support Summit 1553 Functionality\n");
return bQuit;
}
bool_t IsSUMMIT1553(uint32_t moduleID)
{
bool_t bSupportSUM1553Func = FALSE;
switch (moduleID)
{
case NAI_MODULE_ID_N7:
case NAI_MODULE_ID_N8:
case NAI_MODULE_ID_NA:
case NAI_MODULE_ID_NB:
case NAI_MODULE_ID_NC:
bSupportSUM1553Func = TRUE;
break;
default:
bSupportSUM1553Func = FALSE;
break;
}
return bSupportSUM1553Func;
}
bool_t IsFTx1553(uint32_t moduleID)
{
bool_t bSupportFTx1553Func = FALSE;
switch (moduleID)
{
case NAI_MODULE_ID_FT0:
case NAI_MODULE_ID_FT1:
case NAI_MODULE_ID_FT2:
case NAI_MODULE_ID_FT3:
case NAI_MODULE_ID_FT4:
case NAI_MODULE_ID_FT5:
case NAI_MODULE_ID_FT6:
case NAI_MODULE_ID_FT7:
case NAI_MODULE_ID_FT8:
case NAI_MODULE_ID_FT9:
case NAI_MODULE_ID_FTA:
case NAI_MODULE_ID_FTB:
case NAI_MODULE_ID_FTC:
case NAI_MODULE_ID_FTD:
case NAI_MODULE_ID_FTE:
case NAI_MODULE_ID_FTF:
case NAI_MODULE_ID_FTPIB:
case NAI_MODULE_ID_FTK:
case NAI_MODULE_ID_CM1:
case NAI_MODULE_ID_CM5:
case NAI_MODULE_ID_CM8:
case NAI_MODULE_ID_IF2:
bSupportFTx1553Func = TRUE;
break;
default:
bSupportFTx1553Func = FALSE;
break;
}
return bSupportFTx1553Func;
}
bool_t IsFTx1760(uint32_t moduleID)
{
bool_t bSupportFTx1760Func = FALSE;
switch (moduleID)
{
case NAI_MODULE_ID_FTK:
bSupportFTx1760Func = TRUE;
break;
default:
bSupportFTx1760Func = FALSE;
break;
}
return bSupportFTx1760Func;
}
bool_t Get1553LogicalDevNum(int16_t defdevnum, int16_t *devnum)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nSelect Logical Device Number (0-31). This must be a unique number specific to this channel/device. [Default=%d]: ", defdevnum);
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*devnum = defdevnum;
bValidEntry = TRUE;
}
else if (atoi((char *)inputBuffer) < 0 || atoi((char *)inputBuffer) > 31)
printf("\nPlease Select a Valid Logical Device Number (0-31) [Default=%d]: ", defdevnum);
else
{
*devnum = (int16_t)atoi((char *)inputBuffer);
bValidEntry = TRUE;
}
}
}
return bQuit;
}
bool_t Get1553RTAddressSource(bool_t defSoftware, bool_t *bSoftware)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nSelect RT Address Source (S - Software, E - External Inputs) [Default=%s]: ", defSoftware ? "S" : "E");
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*bSoftware = defSoftware;
bValidEntry = TRUE;
}
else if ((toupper(inputBuffer[0]) != 'S') && (toupper(inputBuffer[0]) != 'E'))
printf("\nPlease Select a Valid RT Address Source (S - Software, E - External Inputs) [Default=%s]: ", defSoftware ? "S" : "E");
else
{
*bSoftware = (toupper(inputBuffer[0]) == 'S') ? TRUE : FALSE;
bValidEntry = TRUE;
}
}
}
return bQuit;
}
bool_t Get1553BCSoftwareOverride(bool_t defSoftware, bool_t *bSoftware)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nOverride External Inputs (Y or N)? [Default=%s]: ", defSoftware ? "Y" : "N");
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*bSoftware = defSoftware;
bValidEntry = TRUE;
}
else if ((toupper(inputBuffer[0]) != 'Y') && (toupper(inputBuffer[0]) != 'N'))
printf("\nPlease Input Y or N. Override External Inputs? [Default=%s]: ", defSoftware ? "Y" : "N");
else
{
*bSoftware = (toupper(inputBuffer[0]) == 'Y') ? TRUE : FALSE;
bValidEntry = TRUE;
}
}
}
return bQuit;
}
bool_t Get1553BCAsyncMsgType(bool_t defPriorityHigh, bool_t *bHighPriority)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nAsync Message Type High or Low (H or L)? [Default=%s]: ", defPriorityHigh ? "H" : "L");
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*bHighPriority = defPriorityHigh;
bValidEntry = TRUE;
}
else if ((toupper(inputBuffer[0]) != 'H') && (toupper(inputBuffer[0]) != 'L'))
printf("\nPlease Input H or L. Async Message Type High or Low (H or L)? [Default=%s]: ", defPriorityHigh ? "H" : "L");
else
{
*bHighPriority = (toupper(inputBuffer[0]) == 'H') ? TRUE : FALSE;
bValidEntry = TRUE;
}
}
}
return bQuit;
}
bool_t Get1760EEPROMCopy(bool_t defCopyToEEPROM, bool_t* bCopyToEEPROM)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nWrite Memory Contents to EEPROM? [Default=%s]: ", defCopyToEEPROM ? "Y" : "N");
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*bCopyToEEPROM = defCopyToEEPROM;
bValidEntry = TRUE;
}
else if ((toupper(inputBuffer[0]) != 'Y') && (toupper(inputBuffer[0]) != 'N'))
printf("\nPlease Input Y or N. Write Memory Contents to EEPROM? [Default=%s]: ", defCopyToEEPROM ? "Y" : "N");
else
{
*bCopyToEEPROM = (toupper(inputBuffer[0]) == 'Y') ? TRUE : FALSE;
bValidEntry = TRUE;
}
}
}
return bQuit;
}
bool_t Get1553RxBufferType(uint16_t defrxbuffertype, uint16_t *rxbuffertype)
{
bool_t bQuit = FALSE;
bool_t bValidEntry = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nSelect Rx Buffer Mode:\n\n");
printf("Single Buffer 1-32 (number represents size of buffer)\n");
printf("Double Buffer 33\n");
printf("Circular Buffer - 128 words 34\n");
printf("Circular Buffer - 256 words 35\n");
printf("Circular Buffer - 512 words 36\n");
printf("Circular Buffer - 1024 words 37\n");
printf("Circular Buffer - 2048 words 38\n");
printf("Circular Buffer - 4096 words 39\n");
printf("Circular Buffer - 8192 words 40\n");
printf("Global Circular Buffer - 128 words 41\n");
printf("Global Circular Buffer - 256 words 42\n");
printf("Global Circular Buffer - 512 words 43\n");
printf("Global Circular Buffer - 1024 words 44\n");
printf("Global Circular Buffer - 2048 words 45\n");
printf("Global Circular Buffer - 4096 words 46\n");
printf("Global Circular Buffer - 8192 words 47\n");
printf("\n\nEnter a Number between 1 and 47 [Default=%d]: ", defrxbuffertype);
while (!bValidEntry)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
*rxbuffertype = defrxbuffertype;
bValidEntry = TRUE;
}
else if (atoi((char *)inputBuffer) < 1 || atoi((char *)inputBuffer) > 47)
printf("\nPlease Enter a valid Number between 1 and 47 [Default=%d]: ", defrxbuffertype);
else
{
*rxbuffertype = (uint16_t)atoi((char *)inputBuffer);
bValidEntry = TRUE;
}
}
}
return bQuit;
}
/****** Command Tables *******/
static nai_1553_cmdtbl_type NAI_MenuCmds[25];
void Load1553MenuCommands(int32_t menuCmdCnt, nai_1553_cmdtbl_type menuCmds[])
{
int32_t i;
g_MenuCmdCnt = menuCmdCnt;
/* Load the NAI_MenuCmds structure */
for (i = 0; i < g_MenuCmdCnt; i++)
{
strcpy((char *)NAI_MenuCmds[i].cmdstr, (const char *)menuCmds[i].cmdstr);
strcpy((char *)NAI_MenuCmds[i].menustr, (const char *)menuCmds[i].menustr);
NAI_MenuCmds[i].cmdnum = menuCmds[i].cmdnum;
NAI_MenuCmds[i].func = menuCmds[i].func;
}
}
void Display1553MenuCommands(int8_t *menuTitle)
{
int32_t i;
printf("\n\n\n\t\t %s\n ", menuTitle);
printf("\n ======== Command Selections ===============");
for (i=0; i < g_MenuCmdCnt && NAI_MenuCmds[i].cmdstr != NULL; i++)
printf ("\n %-8s \t%s", NAI_MenuCmds[i].cmdstr, NAI_MenuCmds[i].menustr);
printf("\n");
}
bool_t Get1553CmdNum(int32_t cmdrequestCnt, int8_t *cmdrequest, int32_t* cmdNum)
{
bool_t bCmdFound = FALSE;
int32_t i;
for (i = 0; i < g_MenuCmdCnt; i++)
{
if (naiapp_strnicmp(cmdrequest, NAI_MenuCmds[i].cmdstr, cmdrequestCnt) == 0)
{
bCmdFound = TRUE;
*cmdNum = i;
break;
}
}
return bCmdFound;
}
void Menu1553Command(int32_t cmd, int16_t devnum)
{
NAI_MenuCmds[cmd].func(devnum);
}
void LoadIllegalization(int16_t devnum, int32_t channel)
{
uint8_t filename[128];
FILE* deffile = NULL;
int8_t buffer[128];
int8_t *pval;
uint32_t count = 0;
sprintf((char *)filename, "illegalizationCh%d.txt", channel);
deffile = fopen((const char *)filename,"r");
if (deffile != NULL)
{
while (fgets((char*)buffer,sizeof(buffer),deffile) && count < 0x100)
{
pval = (int8_t*)strchr((char*)buffer,'\n');
if (pval)
*pval = '\0'; /* Remove LF */
naibrd_1553_WriteMem(devnum, 0x300+count, (uint16_t)atol((const char*)buffer));
count++;
}
fclose(deffile);
}
}
void SaveIllegalization(int16_t devnum, int32_t channel)
{
uint8_t filename[128];
FILE* deffile = NULL;
int32_t i;
sprintf((char *)filename, "illegalizationCh%d.txt", channel);
deffile = fopen((const char *)filename,"w");
if (deffile != NULL)
{
for (i = 0x300; i <= 0x3FF; i++)
{
fprintf(deffile, "%d\n", naibrd_1553_ReadMem(devnum, i));
}
}
fclose(deffile);
}
bool_t M1553_Config_Registers(int16_t devnum)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
uint16_t registervalue;
uint32_t registeraddr;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Display current state of registers */
DisplayRegisters(devnum);
while (bContinue)
{
/* Prompt User to change the value of a particular register */
printf("\nSelect Register Address (0x00-0x1F) to Set (or Q to quit): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
registeraddr = naiapp_utils_HexStrToDecUInt32((int8_t*)inputBuffer);
if (registeraddr >= 0 && registeraddr < 32)
{
while (bContinue)
{
printf("\nEnter the value (0x0000-0xFFFF) to set (or Q to quit): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
registervalue = naiapp_utils_HexStrToDecUInt16((int8_t*)inputBuffer);
check_status(naibrd_1553_WriteReg(devnum, registeraddr, registervalue));
bContinue = FALSE;
}
else
printf("\nInvalid Value. \n");
}
else
bContinue = FALSE;
}
}
else
printf("\nInvalid Value. \n");
}
else
bContinue = FALSE;
}
return FALSE;
}
bool_t M1553_Aux_Registers(int16_t devnum)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
uint16_t registervalue;
uint32_t registeraddr;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Display current state of aux registers */
DisplayAuxRegisters(devnum);
while (bContinue)
{
/* Prompt User to change the value of a particular register */
printf("\nSelect Auxiliary Register Address (0x00-0xF) to Set (or Q to quit): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
registeraddr = naiapp_utils_HexStrToDecUInt32((int8_t*)inputBuffer);
if (registeraddr >= 0 && registeraddr < 32)
{
while (bContinue)
{
printf("\nEnter the value (0x0000-0xFFFF) to set (or Q to quit): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
registervalue = naiapp_utils_HexStrToDecUInt16((int8_t*)inputBuffer);
check_status(naibrd_1553_WriteAuxReg(devnum, registeraddr, registervalue));
bContinue = FALSE;
}
else
printf("\nInvalid Value. \n");
}
else
bContinue = FALSE;
}
}
else
printf("\nInvalid Value. \n");
}
else
bContinue = FALSE;
}
return FALSE;
}
void DisplayRegisters(int16_t devnum)
{
int32_t i;
uint16_t registervalue;
printf("\n\n");
printf("********** CONFIGURATION REGISTERS **********\n");
printf("ADDRESS VALUE \n");
for (i = 0; i < 32; i++)
{
registervalue = naibrd_1553_ReadReg(devnum, i);
printf(" 0x%02X 0x%02X \n", i, registervalue);
}
printf("\n\n");
}
void DisplayAuxRegisters(int16_t devnum)
{
int32_t i;
uint16_t registervalue;
printf("\n\n");
printf("********** AUXILLARY REGISTERS **********\n");
printf("ADDRESS VALUE \n");
for (i = 0; i < 16; i++)
{
registervalue = naibrd_1553_ReadAuxReg(devnum, i);
printf(" 0x%02X 0x%02X \n", i, registervalue);
}
printf("\n\n");
}
bool_t GetRTAddress(int32_t* nRTaddress)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int32_t value;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while (bContinue)
{
printf("\nWhat is the RT Address of the command word (0 to 31)? ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
value = atoi((const char*)inputBuffer);
if (value >= 0 && value < 32)
{
*nRTaddress = value;
bContinue = FALSE;
}
else
printf("\nInvalid Command.\n");
}
else
bContinue = FALSE;
}
return bQuit;
}
bool_t GetTxRx(bool_t* bTxMsg)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while (bContinue)
{
printf("\nReceive (R) or Transmit (T) Message? ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (toupper(inputBuffer[0]) == 'R')
{
*bTxMsg = FALSE;
bContinue = FALSE;
}
else if (toupper(inputBuffer[0]) == 'T')
{
*bTxMsg = TRUE;
bContinue = FALSE;
}
else
printf("\nInvalid Command.\n");
}
else
bContinue = FALSE;
}
return bQuit;
}
bool_t GetSubaddress(int32_t* nSubaddress)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int32_t value;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while (bContinue)
{
printf("\nSubaddress (0 to 31)? ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
value = atoi((const char*)inputBuffer);
if (value >= 0 && value < 32)
{
*nSubaddress = value;
bContinue = FALSE;
}
else
printf("\nInvalid Command.\n");
}
else
bContinue = FALSE;
}
return bQuit;
}
bool_t GetWordCount(int32_t* nWordCount)
{
bool_t bContinue = TRUE;
bool_t bQuit = FALSE;
int32_t value;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while (bContinue)
{
printf("\nWord Count (1 to 32)? ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
value = atoi((const char*)inputBuffer);
if (value > 0 && value <= 32)
{
*nWordCount = value;
bContinue = FALSE;
}
else
printf("\nInvalid Command.\n");
}
else
bContinue = FALSE;
}
return bQuit;
}
int32_t MemoryTest(int16_t devnum)
{
int32_t counter = 0;
int32_t ErrCnt = 0;
uint16_t testValues[6] = {0x0000, 0x5555, 0xAAAA, 0xA5A5, 0x5A5A, 0xFFFF};
uint16_t readValue;
int32_t i;
printf("\nDevNum %d - Memory Test started. Please wait for test to complete...\n\n", devnum);
while (counter < NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY)
{
for (i = 0; i < sizeof(testValues)/sizeof(testValues[0]); i++)
{
naibrd_1553_WriteMem(devnum, counter, testValues[i]);
readValue = naibrd_1553_ReadMem(devnum, counter);
/* If write/read values do not match */
if (readValue != testValues[i])
{
ErrCnt++;
printf("\nData Mismatch! Memory Location: 0x%04X, WriteVal: 0x%04X, ReadVal: 0x%04X, ErrCnt: %d\n\n", counter, testValues[i], readValue, ErrCnt);
}
}
counter++;
/* Display Progress */
if ((counter % 1000) == 250)
printf("\\ %d%% Complete\r", (counter*100)/NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY);
else if ((counter % 1000) == 500)
printf("| %d%% Complete\r", (counter*100)/NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY);
else if ((counter % 1000) == 750)
printf("/ %d%% Complete\r", (counter*100)/NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY);
else if ((counter % 1000) == 0)
printf("- %d%% Complete\r", (counter*100)/NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY);
}
printf("\nDevNum %d - Memory Test Complete. ErrCnt = %d\n\n", devnum, ErrCnt);
return ErrCnt;
}
int32_t MemoryTestFast(int16_t cardIndex, int16_t module, int16_t channel)
{
int32_t ErrCnt = 0;
uint16_t testValues[6] = {0x0000, 0x5555, 0xAAAA, 0xA5A5, 0xFFFF};
uint32_t testValues32[6] = {0x00000000, 0x55555555, 0xAAAAAAAA, 0xA5A5A5A5, 0xFFFFFFFF};
int32_t i,j,testIndex;
uint16_t data[NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY];
uint32_t data32[NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY];
uint16_t readdata[NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY];
uint32_t readdata32[NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY];
uint32_t M1553memory[4] = NAI_1553_GEN5_REG_MEMORY_ADD;
uint32_t M1553memory32[4] = NAI_1553_GEN5_32BIT_REG_MEMORY_ADD;
uint32_t modid;
int32_t maxmemorysize;
uint32_t modprocrev, modfpgarev;
printf("\nChannel %d - Memory Test started. Please wait for test to complete...\n\n", channel);
modid = naibrd_GetModuleID(cardIndex, module);
naibrd_GetModuleRev(cardIndex, module, &modprocrev, &modfpgarev);
if (modfpgarev >= 0x100)
memcpy(M1553memory, M1553memory32, sizeof(uint32_t)*4);
if (modid == NAI_MODULE_ID_FT3 || modid == NAI_MODULE_ID_FT6 || modid == NAI_MODULE_ID_FT9)
maxmemorysize = NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY / 2;
else
maxmemorysize = NAI_1553_MAX_SIZE_OF_DEVICE_MEMORY;
for (i = 0; i < sizeof(testValues)/sizeof(testValues[0]); i++)
{
for (testIndex = 0; testIndex < maxmemorysize; testIndex++)
{
if (i == 0)
{
data[testIndex] = testValues[i]++;
if (modfpgarev >= 0x100)
data32[testIndex] = testValues32[i]++;
else
data32[testIndex] = testValues[i]++;
}
else
{
data[testIndex] = testValues[i];
if (modfpgarev >= 0x100)
data32[testIndex] = testValues32[i];
else
data32[testIndex] = testValues[i];
}
}
if (i == 0)
printf("Writing Incremental Data to %d words in RAM\n", maxmemorysize);
else
{
if (modfpgarev >= 0x100)
printf("Writing 0x%08X to %d words in RAM\n", testValues32[i], maxmemorysize);
else
printf("Writing 0x%04X to %d words in RAM\n", testValues[i], maxmemorysize);
}
if (modfpgarev >= 20)
naibrd_Write32(cardIndex, module, M1553memory[channel - 1] << 1, 4, maxmemorysize, NAI_REG32, data32);
else
naibrd_Write16(cardIndex, module, M1553memory[channel - 1], 2, maxmemorysize, NAI_REG16, data);
printf("Reading %d words in RAM\n", maxmemorysize);
if (modfpgarev >= 20)
naibrd_Read32(cardIndex, module, M1553memory[channel - 1] << 1, 4, maxmemorysize, NAI_REG32, &readdata32[0]);
else
naibrd_Read16(cardIndex, module, M1553memory[channel - 1], 2, maxmemorysize, NAI_REG16, &readdata[0]);
for (j = 0; j < maxmemorysize; j++)
{
/* If write/read values do not match */
if (modfpgarev >= 20)
{
if (readdata32[j] != data32[j])
{
ErrCnt++;
printf("\nData Mismatch! Memory Location: 0x%04X, WriteVal: 0x%04X, ReadVal: 0x%04X, ErrCnt: %d\n\n", j, data32[j], readdata32[j], ErrCnt);
}
}
else
{
if (readdata[j] != data[j])
{
ErrCnt++;
printf("\nData Mismatch! Memory Location: 0x%04X, WriteVal: 0x%04X, ReadVal: 0x%04X, ErrCnt: %d\n\n", j, data[j], readdata[j], ErrCnt);
}
}
}
if (ErrCnt == 0)
{
printf("Test Passed\n");
}
}
printf("\nChannel %d - Memory Test Complete. ErrCnt = %d\n\n", channel, ErrCnt);
return ErrCnt;
}