Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

M1553 RT Receive

M1553 RT Receive Sample Application (SSK 1.x)

Overview

The M1553 RT Receive sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT) with stack-based message retrieval 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), broadcast receive support, and stack-based raw message decoding.

The key message retrieval API calls demonstrated are:

  • naibrd_1553_RtMessageGetFromStackRaw() — reads one raw message at a time from the RT command stack.

  • naibrd_1553_RtMessageDecodeRaw() — decodes the raw message into a structured format with block status, time tag, command word, and data payload.

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_Receive executable from your build output directory. On startup the application looks for a configuration file (default_1553_RTReceive.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, address source, 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:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_1553_RTReceive.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.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleID() so downstream code can adapt to the specific 1553 variant installed.

  5. If a valid module is found, call Run_M1553_RT_Receive() to begin RT configuration and message processing.

#if defined (__VXWORKS__)
int32_t M1553_RT_Receive(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_M1553_RT_Receive(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:

  • No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.

  • Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain a 1553 module. Use the board menu to verify which slots are populated.

Program Structure

Entry Point

The program entry point is main() on most platforms or M1553_RT_Receive() on VxWorks. After the board connection and module selection described above, the application calls Run_M1553_RT_Receive(), 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 Run_M1553_RT_Receive(), 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:

  1. 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.

  2. Get1553Address() — prompts for the subaddress to legalize for Tx, Rx, and broadcast traffic. Valid subaddresses are 1 through 31. The default is subaddress 2.

  3. 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.

  4. 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 calls naibrd_1553_RtSetAddress() to program the address. When hardware addressing is selected, the RT address is read from the module’s physical address pins.

  5. 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, and decodes any new messages from the stack. The user specifies the loop duration in seconds before each run.

Internal Loopback Test

Before opening the device, the sample optionally runs an internal loopback test to verify that the 1553 hardware is functioning correctly on both Bus A and Bus B. To perform this verification in your own application, call naibrd_1553_InternalLoopback():

swResult = naibrd_1553_InternalLoopback(cardIndex, module, rtchan, &busAPassed, &busBPassed);
if (swResult == NAI_SUCCESS)
{
   printf("Bus A Internal Loopback Test %s\n", busAPassed ? "PASSED" : "FAILED");
   printf("Bus B Internal Loopback Test %s\n", busBPassed ? "PASSED" : "FAILED");
}

This test transmits and receives data internally on the module without requiring an external bus connection. It confirms that the transceiver and protocol engine are operational. A failure on either bus indicates a hardware issue that should be investigated before proceeding.

Important
  • Loopback test failure — indicates a potential hardware fault on that bus. Check cabling and module seating. Consult the FTA-FTF Manual for diagnostic procedures.

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 call naibrd_1553_RtSetAddressSource() to select internal addressing, and 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(), then call naibrd_1553_RtSetAddressSource() with NAI_1553_RT_ADDR_SOURCE_EXTERNAL. The RT address is read from the module’s external address pins. Hardware pin addressing is required in some MIL-STD-1760 installations where the platform wiring determines the RT address.

Address Verification

After configuration, the sample reads back both the address source and the address value to confirm they were set correctly:

swResult = naibrd_1553_RtGetAddressSource(DevNum, &usData);
printf("\nRT Address set %sly ", (usData == NAI_1553_RT_ADDR_SOURCE_INTERNAL) ? "internal" : "external");

swResult = naibrd_1553_RtGetAddress(DevNum, &usData);
printf("to %d\n\n", usData);

To verify your RT address configuration in your own application, call naibrd_1553_RtGetAddressSource() and naibrd_1553_RtGetAddress() after setup.

RT Address Relatch

When using hardware pin addressing, the RT address is latched at startup. If the physical address pins change after the RT has been configured, the sample provides an option to relatch the address by calling naibrd_1553_RtAddressRelatch(). This re-reads the external pins and updates the RT address without reinitializing the device.

if (bSoftwareRTAddr)
{
   /* Set RTAD_SW_EN and RT_ADR_LAT in software */
   swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0018);
   swResult = naibrd_1553_RtSetAddressSource(DevNum, NAI_1553_RT_ADDR_SOURCE_INTERNAL);

   /* Set RT address */
   swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr);
}
else
{
   /* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
   swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
   swResult = naibrd_1553_RtSetAddressSource(DevNum, NAI_1553_RT_ADDR_SOURCE_EXTERNAL);
}

For complete register bit definitions, refer to the FTA-FTF Manual.

Important
  • RT not responding — verify that the address and source mode match. A common mistake is configuring software addressing while the hardware is wired for pin addressing, or vice versa. If the source mode does not match, the RT will have the wrong address (or no valid address) and will not respond to BC commands.

  • RT address conflict — two RTs with the same address on the same bus cause unpredictable behavior. Each RT on a bus must have a unique address (0-30). Address 31 is reserved for broadcast and must not be assigned to any RT.

Buffer Types and Data Block Configuration

This section covers how the sample creates and maps data blocks for Rx, broadcast, 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 an Rx data block and a broadcast Rx data block, both mapped 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);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_RX, sa, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);

/* Create a Broadcast Rx Buffer data block and map to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_BCST, nDataBlockType, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_BCST, sa, NAI_1553_RT_MESSAGE_TYPE_BROADCAST, 0, 1);

naibrd_1553_RtDataBlockCreate() allocates the data block on the module. DevNum is the logical device handle, DATA_BLOCK_ID_RX (or DATA_BLOCK_ID_BCST) 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, the message type constant determines direction (NAI_1553_RT_MESSAGE_TYPE_RX for receive, NAI_1553_RT_MESSAGE_TYPE_BROADCAST for broadcast 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);
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_TX1, sa, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
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
  • Data block creation failure — verify that the block type is valid (NAI_1553_RT_DATABLOCK_SINGLE_32, NAI_1553_RT_DATABLOCK_DOUBLE, or circular) and that the block ID has not already been allocated. An invalid type or duplicate ID will cause naibrd_1553_RtDataBlockCreate() to return a non-zero error code.

  • Subaddress mapping failure — the subaddress must be in the range 1-30 and the data block must already be created before calling naibrd_1553_RtDataBlockMapToSubaddress(). Passing an out-of-range subaddress or an uncreated block ID will fail.

  • Tx data stale — after writing new data to the inactive Tx block, you must call naibrd_1553_RtTxDataBlockSwap() to make it active. Forgetting the swap means the BC continues reading the old block and the updated data is never transmitted.

Message Processing Loop

The ProcessMessages() function is the core runtime loop. It runs for a user-specified duration (default 5 seconds), polling the RT command stack every 10 ms (nai_msDelay(10)) for new messages. On each iteration it reads raw messages from the stack, decodes them, 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)
{
   if (currDataBlock == DATA_BLOCK_ID_TX1)
   {
      UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX2);
      naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX2, Subaddress);
      currDataBlock = DATA_BLOCK_ID_TX2;
   }
   else
   {
      UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX1);
      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;

   for (i = 0; i < 32; i++)
   {
      wBuffer[i] += 1;
   }

   swResult = naibrd_1553_RtDataBlockWrite(DevNum, nDataBlkID, wBuffer, RTBC_WORDCNT, 0);
   if (swResult < 0)
   {
      printf("Error: naibrd_1553_RtDataBlockWrite %d\n\n", swResult);
      return 0;
   }
   return 1;
}

Stack-Based Message Retrieval

Each iteration calls naibrd_1553_RtMessageGetFromStackRaw() to read one raw message from the RT command stack. If the return value is greater than 0, a message is available and the sample proceeds to decode it. If the return value is 0, no new messages have arrived. A negative return value indicates an error.

swResult = naibrd_1553_RtMessageGetFromStackRaw(DevNum, wsBuffer, NAI_1553_MAX_MESSAGE_SIZE_RT);
if (swResult < 0)
{
   printf("Error: naibrd_1553_RtMessageGetFromStackRaw %d\n\n", swResult);
   return 0;
}
else if (swResult > 0)
{
   /* Decode Raw Message */
   swResult = naibrd_1553_RtMessageDecodeRaw(DevNum, wsBuffer, &DecodedMsgStruct);
}

The 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 reads messages out, older messages are lost. To avoid this, call naibrd_1553_RtMessageGetFromStackRaw() frequently enough to keep up with the incoming message rate.

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 ((DecodedMsgStruct.wCommandWord1 & 0x0400) != 0x0400)   /* If this is a Rx message */
{
   printf("Rx Msg Received\n");
   printf("Block Status - 0x%04X\n", DecodedMsgStruct.wBlockStatus);
   printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
   printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
   printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.wDataWordCount);
   printf("Data:");
   for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
   {
      printf("0x%04X ", DecodedMsgStruct.waData[i]);
   }
}
else
{
   printf("Tx Msg Received\n");
   printf("Block Status - 0x%04X\n", DecodedMsgStruct.wBlockStatus);
   printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
   printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
   printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.wDataWordCount);
}

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.

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
  • No messages appearing — verify that the RT has been started with naibrd_1553_RtStart(), the subaddress is legalized, and the BC is targeting this RT address and subaddress.

  • Stack overflow / messages lost — naibrd_1553_RtMessageGetFromStackRaw() is not being called frequently enough. Increase the polling rate or reduce the BC message rate. For high-rate applications, consider using the host buffer approach (see the M1553_RT_HBuff sample) or FIFO mode (see the M1553_RT_Receive_FIFO sample).

  • Tx data not updating — naibrd_1553_RtTxDataBlockSwap() is not being called, or the application is writing to the wrong (active) block instead of the inactive block.

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, 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.

Loopback test failure

Hardware fault on Bus A or Bus B

Check module seating and cabling. Consult the module manual for diagnostics.

RT address mismatch

RT address doesn’t match what BC is targeting

Confirm address set via RtSetAddress() or hardware pins matches BC command word.

RT address source conflict

Software address set but hardware pin mode active, or vice versa

Match WriteAuxReg(0x2, …​) value to desired source: 0x0018 for software, 0x0008 for hardware pins.

Subaddress not legalized

Data block mapped without legalization flag

Set bIsSubaddressLegalizationRequested = 1 in RtDataBlockMapToSubaddress().

No messages appearing

RT not started, subaddress not legalized, or BC not sending to this RT/subaddress

Verify RtStart() was called, subaddress is legalized, and BC is targeting correct address/subaddress.

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

RtTxDataBlockSwap() not called after updating inactive block

Always swap after writing to the inactive block. Verify currDataBlock tracking is correct.

Stack overflow / lost messages

Application not reading from stack frequently enough

Increase polling rate, reduce loop delay, or switch to host buffer or FIFO approach.

Rx data tearing

Wrong buffer type for message rate — single buffer under load

Switch to double-buffered (NAI_1553_RT_DATABLOCK_DOUBLE) or circular for higher rates.

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_Receive.c (SSK 1.x)
#include <stdio.h>
#include <ctype.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_RTReceive.txt";

/* Function prototypes */
static bool_t Run_M1553_RT_Receive(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 uint16_t DATA_BLOCK_ID_BCST  = 4;

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_Receive is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Remote Terminal, legalize Subaddress 2 for Tx, Rx and Broadcast messages, and set it up to receive data
using double buffers 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 Tx message is received, the data in the active Tx buffer will be sent to the bus. While the RT is running, Tx
buffer data will be updated periodically by incrementing all 32 data words of Tx data.
This application demonstrates the usage of the following naibrd 1553 routines.
 - naibrd_1553_GetChannelCount
 - naibrd_1553_InternalLoopback
 - naibrd_1553_Open
 - naibrd_1553_Initialize
 - naibrd_1553_WriteAuxReg
 - naibrd_1553_RtSetAddress
 - naibrd_1553_RtGetAddress
 - naibrd_1553_RtSetAddressSource
 - naibrd_1553_RtGetAddressSource
 - naibrd_1553_RtDataBlockCreate
 - naibrd_1553_RtDataBlockMapToSubaddress
 - naibrd_1553_RtDataBlockWrite
 - naibrd_1553_RtAddressRelatch
 - naibrd_1553_RtStart
 - naibrd_1553_RtStop
 - naibrd_1553_RtTxDataBlockSwap
 - naibrd_1553_RtMessageGetFromStackRaw
 - naibrd_1553_RtMessageDecodeRaw
 - naibrd_1553_Free

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_Receive(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_M1553_RT_Receive(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 Run_M1553_RT_Receive(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;
   bool_t busAPassed, busBPassed;
   uint16_t usData;
   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;
   }

   /* OPTIONAL: Loopback Test to verify hardware operation */
   swResult = naibrd_1553_InternalLoopback(cardIndex, module, rtchan, &busAPassed, &busBPassed);
   if (swResult == NAI_SUCCESS)
   {
      printf("Bus A Internal Loopback Test %s\n", busAPassed ? "PASSED" : "FAILED");
      printf("Bus B Internal Loopback Test %s\n", busBPassed ? "PASSED" : "FAILED");
   }

   /* 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);
      swResult = naibrd_1553_RtSetAddressSource(DevNum, NAI_1553_RT_ADDR_SOURCE_INTERNAL);

      /* 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 */
      /* NOTE: If RT_ADR_LAT is not set, the device RT address will always reflect the state of the */
      /* RT address pins, even if the state changes while the RT is running. This behavior is */
      /* undesirable in most applications of 1553. */
      swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
      swResult = naibrd_1553_RtSetAddressSource(DevNum, NAI_1553_RT_ADDR_SOURCE_EXTERNAL);
   }

   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;
   }

   /* Get RT Address Source (External Pins or Internal via Software) */
   swResult = naibrd_1553_RtGetAddressSource(DevNum, &usData);
   if(swResult != 0)
   {
      bQuit = TRUE;
      printf("Error: naibrd_1553_RtGetAddressSource  %d", swResult);
      return bQuit;
   }

   printf("\nRT Address set %sly ", (usData == NAI_1553_RT_ADDR_SOURCE_INTERNAL) ? "internal" : "external");

   /* Read RT Address */
   swResult = naibrd_1553_RtGetAddress(DevNum, &usData);
   if(swResult != 0)
   {
      bQuit = TRUE;
      printf("Error: naibrd_1553_RtGetAddress  %d", swResult);
      return bQuit;
   }

   printf("to %d\n\n", usData);

   /* 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 a Broadcast Rx Buffer data block and map to the desired subaddress */
   swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_BCST, 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_BCST, sa, NAI_1553_RT_MESSAGE_TYPE_BROADCAST, 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)
   {
      /* If the RT address is being read from external pins, give the user the option to relatch the RT address before running the RT */
      if (!bSoftwareRTAddr)
      {
         printf("\nRelatch RT Address (Y or N)? ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (toupper(inputBuffer[0]) == 'Y')
            {
               naibrd_1553_RtAddressRelatch(DevNum);
            }
         }
      }

      /* Run the RT */
      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);
         }

         /* 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;
   }

   /* 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;
   naiDecodedMessageStructure DecodedMsgStruct;
   uint16_t wsBuffer[72] = { 0x0000 };
   int32_t count = 0;

   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;
      }

      /* If the stack pointer has updated (new data arrived), read one message at a time */
      swResult = naibrd_1553_RtMessageGetFromStackRaw(DevNum, wsBuffer, NAI_1553_MAX_MESSAGE_SIZE_RT);
      if (swResult < 0)
      {
         printf("Error: naibrd_1553_RtMessageGetFromStackRaw %d\n\n", swResult);
         return 0;
      }
      else if (swResult > 0)
      {
         /* Decode Raw Message */
         swResult = naibrd_1553_RtMessageDecodeRaw(DevNum, wsBuffer, &DecodedMsgStruct);
         if (swResult < 0)
         {
            printf("Error: naibrd_1553_RtMessageDecodeRaw %d\n\n", swResult);
            return 0;
         }

         if ((DecodedMsgStruct.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", DecodedMsgStruct.wBlockStatus);
            printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
            printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
            printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.wDataWordCount);
            printf("Data:");
            for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
            {
               if (i % 8 == 0)
               {
                  printf("\n");
               }
               printf("0x%04X ", DecodedMsgStruct.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", DecodedMsgStruct.wBlockStatus);
            printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
            printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
            printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.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;
}

Help Bot

X