M1553 RT Receive
Edit this on GitLab
M1553 RT Receive
Explanation
About the Sample Application Code
The provided sample application code is a C program designed to interact with embedded function modules using North Atlantic Industries' (NAI) Software Support Kit (SSK). The code focuses on configuring and operating a 1553 channel as a Remote Terminal (RT) for receiving and transmitting data.
Overview
This application demonstrates how to set up a 1553 channel, configure transmit (Tx) and receive (Rx) data blocks, and manage the data transmission and reception process using NAI’s library of functions. The program utilizes multiple NAI library functions to cover various aspects of working with the 1553 channel.
Key Points
Included Libraries and Headers
-
Standard C Libraries: These include standard input/output, string manipulation, and other utility functions.
-
NAI-Specific Include Files: These facilitate board access, query capabilities, display functions, and 1553 specific utilities.
-
Function-Specific Include Files: These target specific functionalities, such as
naibrd_1553
, for working with the 1553 protocol.
Constants and Global Variables
-
Configuration File:
CONFIG_FILE
points to the configuration file for default settings. -
Sample Program Constants: Constants for different data block IDs and default channel/RT parameters are defined.
-
Global Variables:
currDataBlock
tracks the current Tx data block in use.
Main Function
The main
function initializes the program, interacts with the user to determine the card and module indexes, and executes the Run_M1553_RT_Receive
function if valid indexes are provided.
Function Prototypes
The sample code includes prototypes for various static functions, encapsulating operations such as: - Run_M1553_RT_Receive: Manages the main execution flow for the RT receiver. - UpdateTxDataBlock: Updates the Tx data block with new data. - UpdateTxBuffer: Writes data to the Tx buffer. - ProcessMessages: Processes incoming messages and decodes them.
Run_M1553_RT_Receive
Function
This is the heart of the application, handling the following:
-
Initialization: Sets up the RT channel, validates RT address, and performs optional loopback tests.
-
Configuration: Configures the 1553 RT, sets RT address source, and creates/maps data blocks (Rx, Broadcast, and Tx).
-
Running the RT: Starts and stops the RT, updates Tx data blocks periodically, and processes incoming messages.
-
Cleanup: Frees the 1553 device once the operations are complete.
Auxiliary Functions
-
UpdateTxDataBlock
: Alternates between two Tx buffers and updates each buffer with new data. -
UpdateTxBuffer
: Increments each data word in the Tx buffer and writes the buffer to the device. -
ProcessMessages
: Continuously processes incoming messages for a specified duration, updates Tx data blocks, and prints the details of received messages.
Enumerations and Inferences
-
Enumerations: The code uses enum-based values like
NAI_1553_RT_DATABLOCK_*
to handle various buffer configurations. -
NAI Functions: The provided summaries and library calls illustrate specific NAI functions such as
naibrd_1553_GetChannelCount
,naibrd_1553_RtSetAddress
,naibrd_1553_RtStart
, etc.
Detailed Example Usage
Setting Up the RT
-
Initialize and Open Device:
---- swResult = naibrd_1553_Open(cardIndex, module, rtchan, DevNum); swResult = naibrd_1553_Initialize(DevNum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_RT, 0, 0, 0); ----
-
Configure RT Address Source:
---- swResult = naibrd_1553_RtSetAddressSource(DevNum, NAI_1553_RT_ADDR_SOURCE_INTERNAL); swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr); ----
-
Create and Map Data Blocks:
---- 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); ----
Running and Processing 1. Start RT and Process Messages:
---- swResult = naibrd_1553_RtStart(DevNum); ProcessMessages(DevNum, sa, duration); swResult = naibrd_1553_RtStop(DevNum); ----
-
Update and Swap Tx Buffers:
---- UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX1); naibrd_1553_RtTxDataBlockSwap(DevNum, DATA_BLOCK_ID_TX1, Subaddress); ----
By following the steps outlined in the code, users can effectively configure and test their 1553 RT setups, handle incoming and outgoing messages, and understand the utilization of NAIs SSK.
#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;
}