M1553 RT Receive FIFO
Edit this on GitLab
M1553 RT Receive FIFO
Explanation
About main.c
- North Atlantic Industries Sample Application Code
This sample application code demonstrates an implementation for configuring and interacting with NAI’s (North Atlantic Industries) embedded function modules, specifically for MIL-STD-1553 communication using the SSK (Software Support Kit).
Overview
The code is intended to guide users on how to call functions from the naibrd
(NAI Board) library to configure a 1553 channel as a Remote Terminal (RT). It also explains how to manage data reception and transmission using double buffers and how to handle message processing via a FIFO (First-In-First-Out) system.
Included Libraries and Header Files:
- Standard C Libraries:
- stdio.h
, ctype.h
, stdlib.h
, string.h
, time.h
- Common Sample Program Libraries:
- Board Access: naiapp_boardaccess_menu.h
, naiapp_boardaccess_query.h
, naiapp_boardaccess_access.h
, naiapp_boardaccess_display.h
, naiapp_boardaccess_utils.h
- 1553 Utilities:
- nai_1553_utils.h
- NAI Board Specific Libraries:
- nai.h
, naibrd.h
- Embedded Function Modules: naibrd_1553.h
, naibrd_1553_assisted.h
Constants:
- CONFIG_FILE
: Points to the configuration file (default_1553_RTReceive_FIFO.txt
).
- Data Block IDs: Constants defined for different data blocks for Tx, Rx, and broadcast communications.
- Default Values: Constants for settings such as default RT channel, RT device number, RT address, and more.
Global Variables:
- currDataBlock
: Tracks the current data block in use.
Main Function:
The main function (main
) determines the program flow:
1. Menu and Query Handling: Uses library functions starting with naiapp_
to configure device settings based on user input.
2. Execution of the RT Program: Once the user selects the appropriate card and module, Run_M1553_RT_Receive_FIFO
is called to start the RT process.
Core Functions:
1. Run_M1553_RT_Receive_FIFO:
- Configures and runs the RT based on user input and configuration settings.
- Internal steps include initializing the RT, setting RT address, creating and mapping data blocks, and handling Tx/Rx message processing.
- Utilizes functions from the naibrd
library for various tasks such as opening the device, initializing it, setting the address, and starting/stopping the RT.
-
UpdateTxDataBlock:
-
Alternates between two Tx buffers (double buffering) and updates the data in the active buffer for transmission.
-
-
ProcessMessages:
-
Handles message reception from the FIFO queue within a given duration.
-
Decodes and prints received messages, distinguishing between Rx and Tx messages.
-
-
UpdateTxBuffer:
-
Increments and writes new data to the Tx buffer for transmission.
-
Function Usage with naibrd
:
The following naibrd
1553 routines are used:
- naibrd_1553_GetChannelCount
: Get the number of available channels.
- naibrd_1553_InternalLoopback
: Perform loopback tests.
- naibrd_1553_Open
: Open the device hardware.
- naibrd_1553_Initialize
: Initialize the device with specified modes.
- naibrd_1553_WriteAuxReg
: Write to auxiliary registers.
- naibrd_1553_RtSetAddress
: Set the RT address.
- naibrd_1553_RtGetAddress
: Retrieve the RT address.
- naibrd_1553_RtSetAddressSource
: Set the RT address source (internal/external).
- naibrd_1553_RtDataBlockCreate
: Create a data block.
- naibrd_1553_RtDataBlockMapToSubaddress
: Map a data block to a subaddress.
- naibrd_1553_RtDataBlockWrite
: Write data to a data block.
- naibrd_1553_RtAddressRelatch
: Relatch the RT address.
- naibrd_1553_RtStart
: Start the Remote Terminal.
- naibrd_1553_RtStop
: Stop the Remote Terminal.
- naibrd_1553_RtTxDataBlockSwap
: Swap Tx data blocks.
- naibrd_1553_RtMessageGetFromStackRaw
: Get raw messages from stack.
- naibrd_1553_RtMessageDecodeRaw
: Decode raw messages.
- naibrd_1553_Free
: Free the device.
System Configuration Functions:
- ConfigDevice
, DisplayDeviceCfg
, GetBoardSNModCfg
, CheckModule
: Helper functions for setup and configuration.
Execution Flow:
1. User Interaction:
- Start with naiapp_RunBoardMenu(CONFIG_FILE)
.
- Query user for card index and module number.
2. RT Configuration:
- Call Run_M1553_RT_Receive_FIFO
with selected card and module.
- Perform internal loopback tests, open device, and initialize it.
- Get and set RT address source (internal/external).
- Create and map Rx/Tx data blocks.
3. Message Handling:
- Run the RT and process messages through FIFO.
- Update buffer data periodically.
By following these structures and functions, the sample application shows how to configure and interact with NAI’s embedded function modules for MIL-STD-1553 communication.
#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"
#include "functions/naibrd_1553_assisted.h"
static const int8_t *CONFIG_FILE = (int8_t *)"default_1553_RTReceive_FIFO.txt";
/* Function prototypes */
static bool_t Run_M1553_RT_Receive_FIFO(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 and message information will be displayed via message FIFO.
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. If a Tx message
is received, the message information will be displayed via message FIFO.
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_FIFO(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_FIFO(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_FIFO(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 | NAI_1553_MESSAGE_FIFO_MODE,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, NAI_1553_RT_DATABLOCK_IRQ_NONE, 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, nDataBlockType, 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, 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_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);
}
swResult = naibrd_1553_ClearMsgFIFO(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_ClearMsgFIFO %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;
}
/* 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 fifoCount;
int32_t currBlockIndex = 0, nextBlockIndex = 0;
naiDecodedMessageStructureFIFO msgStruct;
uint32_t fifoData[1024];
int32_t count = 0;
bool_t FIFIOfullStatusBit;
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;
}
swResult = naibrd_1553_GetMsgFIFOCount(DevNum, &fifoCount);
if (swResult != 0)
{
printf("Error: naibrd_1553_GetMsgFIFOCount %d", swResult);
return TRUE;
}
else
{
if (fifoCount > 0)
{
currBlockIndex = 0;
/* This is necessary because otherwise, fifoData array gets used over and over without getting zero'ed out. */
/* When the array gets decoded, old data may get decoded unintentionally */
memset(fifoData, 0, sizeof(fifoData));
/* Read Message FIFO */
swResult = naibrd_1553_ReadMsgFIFO(DevNum, fifoCount, fifoData);
if (swResult != 0)
{
printf("Error: naibrd_1553_ReadMsgFIFO %d", swResult);
return TRUE;
}
else
{
/* Read Messages */
do
{
swResult = naibrd_1553_DecodeFIFOMsg(fifoData, currBlockIndex, &nextBlockIndex, &msgStruct);
if (swResult == 0)
{
if ((msgStruct.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", msgStruct.wBlockStatus);
printf("Time Tag - 0x%04X\n", msgStruct.wTimeTag);
printf("Command Word - 0x%04X\n", msgStruct.wCommandWord1);
printf("Data Word Count - 0x%04X\n", msgStruct.wDataWordCount);
printf((msgStruct.wDataWordCount > 0) ? ("Data:") : (""));
for (i = 0; i < msgStruct.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", msgStruct.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", msgStruct.wBlockStatus);
printf("Time Tag - 0x%04X\n", msgStruct.wTimeTag);
printf("Command Word - 0x%04X\n", msgStruct.wCommandWord1);
printf("Data Word Count - 0x%04X\n", msgStruct.wDataWordCount);
printf("count: %d\n", count++);
printf("\n\n");
}
}
else if(swResult != (uint32_t)NAI_1553_CMD_NO_MSG_TO_DECODE)
{
printf("Error: naibrd_1553_DecodeFIFOMsg %d", swResult);
return TRUE;
}
/*** IMPORTANT !!! ***/
currBlockIndex = nextBlockIndex;
nai_msDelay(1);
} while ((swResult == NAI_SUCCESS) && (time(NULL) < end));
}
swResult = naibrd_1553_GetMsgFIFOFullStatus(DevNum, NAI_1553_STATUS_REALTIME, &FIFIOfullStatusBit);
if (swResult == NAI_SUCCESS)
{
printf("FIFO status: %d", FIFIOfullStatusBit);
printf((FIFIOfullStatusBit == TRUE) ? " Full\r\n" : " Not full\r\n");
}
else
{
printf("Error: naibrd_1553_GetMsgFIFOFullStatus %d", swResult);
return TRUE;
}
}
}
}
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;
}