SUM1553 BC Scheduler
Edit this on GitLab
SUM1553 BC Scheduler Sample Application (SSK 1.x)
Overview
The SUM1553 BC Scheduler sample application demonstrates how to configure a SUMMIT 1553 channel as a Bus Controller (BC) and run a continuous multi-message schedule using the NAI Software Support Kit (SSK 1.x). The SUMMIT 1553 core (Actel Core1553BRM) executes the schedule autonomously in hardware — your application loads the command and data blocks, starts the scheduler, and then interacts with it at its own pace.
The default schedule defines three messages per 100 ms minor frame cycle:
-
BC-to-RT send — 32 words of data to RT address 1, subaddress 2 (Block A).
-
RT-to-BC receive — 32 words of data from RT address 1, subaddress 2 (Block B).
-
BC-to-RT send — 16 words of data to RT address 1, subaddress 3 (Block C).
After starting the scheduler, the BC loops through these messages indefinitely. Data blocks can be updated while the scheduler is running — the hardware picks up the new data on the next cycle.
|
Important
|
This sample uses the |
Supported Modules
This sample supports SUMMIT 1553 module types: N7, N8, NA, NB, and NC. The helper function IsSUMMIT1553(modid) is used at runtime to confirm that the selected module slot contains a supported SUMMIT 1553 device. Each SUMMIT 1553 module provides up to 2 channels.
|
Note
|
The SUM1553 BC Scheduler can run in conjunction with the SUM1553_RT_PingPong or SUM1553_RT_ProcCtrl companion samples to exercise BC and RT operations together on the same 1553 bus. |
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a SUMMIT 1553 module installed (N7, N8, NA, NB, or NC).
-
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 SUM1553_BC_Scheduler executable from your build output directory. On startup the application looks for a configuration file (default_SUM1553_BCSched.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, you select a BC channel and the scheduler begins executing.
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 SUMMIT 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_SUM1553_BCSched.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()and pass it toRun_SUM1553_BC_Scheduler()for channel configuration.
#if defined (__VXWORKS__)
int32_t SUM1553_BC_Scheduler(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_SUM1553_BC_Scheduler(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 and SUM1553_BC_Scheduler() on VxWorks. Both follow the same logic: run the board menu, then loop over card/module selection until the user quits.
Module Detection
After the user selects a module slot, naibrd_GetModuleID() returns the module identifier. The helper IsSUMMIT1553(modid) (called inside Get1553BCCfg()) validates that the module is a supported SUMMIT 1553 type. SUMMIT 1553 modules provide up to 2 channels, so the BC channel number is constrained accordingly.
User Input Flow
The application walks the user through three selection steps before starting the scheduler:
-
Card index —
naiapp_query_CardIndex()prompts for the board to use. -
Module slot —
naiapp_query_ModuleNumber()prompts for the slot containing the SUMMIT 1553 module. -
BC channel —
Get1553BCCfg()prompts for the channel to configure as the Bus Controller (default channel 2).
Once the channel is selected, Run_SUM1553_BC_Scheduler() takes over. It resets the channel, configures it as a BC, loads the command schedule and data blocks, and starts execution.
Interactive Loop
After the scheduler starts, the hardware runs the three-message schedule continuously in the background. The application enters an interactive loop where:
-
Enter — reads back the RT-to-BC data block (Block B) and displays the received words. This lets you verify that a companion RT is responding.
-
'U' — increments a counter and reloads the BC-to-RT data blocks (Blocks A and C) with updated values. The scheduler picks up the new data on the next cycle.
-
'Q' — stops the BC execution and returns to the card/module selection prompt.
The scheduler runs entirely in hardware between user interactions. You can press Enter repeatedly to poll the latest RT response, or leave it running and update the transmit data whenever you are ready.
SUM1553 Command Block Architecture
The SUMMIT 1553 BC core uses a flat, sequential model for scheduling messages. Understanding this architecture is essential for reading the sample code and for designing your own schedules.
Command Blocks vs. Frames
SUM1553 organizes its schedule as a flat sequence of command blocks — up to 2048 blocks total — rather than the major/minor frame hierarchy used by M1553 FTx modules. Each command block is 8 words wide and contains:
-
An opcode that tells the hardware what action to perform.
-
One or two MIL-STD-1553 command words (depending on whether the message is RT-to-RT).
-
A data block reference identifying where transmit or receive data lives.
-
A branch target (used by branching opcodes).
-
Timing information.
Command blocks execute sequentially starting from the current command block pointer. Execution proceeds to the next block unless a branching opcode redirects it elsewhere.
Data Blocks
SUM1553 supports up to 1024 data blocks, each 32 words in size. Command blocks reference data blocks by index — a BC-to-RT command block points to the data block holding the transmit payload, while an RT-to-BC command block points to the data block where received data will be stored. Data blocks can be read or written by the host application while the scheduler is running.
Opcodes Used in This Sample
The BC Scheduler sample uses three opcodes to build its schedule:
NAI_SUM1553_OPCODE_LOAD_MINOR_FRAME_TIMER-
Sets the minor frame cycle period (100 ms in this sample). This opcode does not transmit a message on the bus — it acts as a timing gate that defines how long each pass through the schedule takes. The hardware waits for the remaining frame time after all messages in the cycle have been sent.
NAI_SUM1553_OPCODE_EXEBLK_CONT-
Execute the message defined by this command block, then continue to the next block. This is the primary opcode for sending and receiving 1553 messages. Each of the three messages in the sample schedule (Blocks A, B, and C) uses this opcode.
NAI_SUM1553_OPCODE_GOTO-
Unconditional branch to the command block specified by the branch target field. The sample places a GOTO as the last command block, pointing back to the first block. This creates a continuous loop so the schedule repeats indefinitely.
Other Available Opcodes
Beyond the three opcodes used in this sample, SUM1553 provides additional opcodes for more advanced scheduling:
-
ENDOFLIST— terminates execution. The BC stops after processing this block. -
SKIP— skip this command block and continue to the next one. -
EXEBLK_BRNCH— execute the message, then branch unconditionally to the target block. -
EXEBLK_BRNCH_COND— execute the message, then branch conditionally based on message status. -
RETRY_COND— retry the current message on the alternate bus if the previous attempt failed.
Refer to the SUMMIT 1553 module manual for detailed descriptions of conditional branching and retry behavior.
Execution Flow
The BC execution flow follows a straightforward sequence:
-
The host application writes command blocks and data blocks into the module memory.
-
The host sets the command block pointer to the first block in the schedule.
-
The host enables BC execution.
-
The hardware begins walking through command blocks sequentially, transmitting and receiving messages as directed by each block’s opcode.
-
When the hardware reaches the GOTO block, it branches back to the beginning of the sequence.
-
The cycle repeats continuously until the host application stops execution.
Command Word and Control Word Macros
The SSK provides two macros for building the packed words that go into command blocks:
NAI_SUM1553_COMMAND_WORD(rt, tx, sa, wcmc)-
Builds a MIL-STD-1553 command word from the RT address, transmit/receive bit, subaddress, and word count (or mode code). This is the standard 16-bit command word defined by MIL-STD-1553B.
NAI_SUM1553_BC_CTRL_WORD(opcode, retries, busa, rtrt, cond)-
Builds the control word stored in the command block. This word encodes the opcode, the number of retries on failure, the bus selection (Bus A or Bus B), whether the message is RT-to-RT, and a condition code for conditional branching opcodes.
|
Note
|
If you are familiar with M1553 FTx BC architecture (major/minor frames via naibrd_1553_BcFrameCreate), SUM1553 is conceptually simpler — command blocks execute in sequence with explicit branching.
|
Device Initialization
Before building the command schedule, the application must reset the SUMMIT 1553 channel and place it into Bus Controller mode. This is handled by two API calls at the start of Run_SUM1553_BC_Scheduler().
First, the channel is reset and the application polls until the reset completes:
/* Reset the channel */
check_status(naibrd_SUM1553_Reset(cardIndex,module,bcchan));
/* Wait for channels to reset */
while(check_status(naibrd_SUM1553_IsResetting(cardIndex,module,bcchan,&resetting)) == NAI_SUCCESS && resetting);
Once the reset finishes, the channel is configured as a Bus Controller:
check_status(naibrd_SUM1553_SetMode(cardIndex,module,bcchan,NAI_SUM1553_OPSTATUS_BC_MODE)); /* Configure as BC */
|
Note
|
SUM1553 device initialization is simpler than M1553 FTx initialization. There is no device open or logical device allocation, no auxiliary register configuration, and no platform-specific reset delay. The card index, module slot, and channel number are passed directly to every API call. |
|
Important
|
|
Message Schedule Configuration
After device initialization, the application builds the five-command schedule that the BC hardware will execute in a continuous loop. Each command is loaded into a sequential command block using naibrd_SUM1553_BC_LoadCmdBlock(), and messages that carry data also load an associated data block via naibrd_SUM1553_BC_LoadDataBlock().
The complete schedule timeline is:
Timer(100ms) → Msg1(BC→RT, SA2, 32w) → Msg2(RT→BC, SA2, 32w) → Msg3(BC→RT, SA3, 16w) → GOTO 0 → repeat
Macro Reference
The two macros used throughout this section pack multiple fields into single 16-bit or 32-bit words:
NAI_SUM1553_BC_CTRL_WORD(opcode, retries, busa, rtrt, cond)-
Builds the control word for a command block. The
opcodefield selects the action (timer load, execute-and-continue, goto, etc.).retriessets the number of automatic retries on failure (1 in this sample).busaselects Bus A (1) or Bus B (0).rtrtindicates an RT-to-RT transfer when set to 1 (0 for all messages in this sample).condprovides a condition code for conditional branching opcodes (0 = unconditional). NAI_SUM1553_COMMAND_WORD(rt, tx, sa, wcmc)-
Builds a standard MIL-STD-1553 command word.
rtis the remote terminal address (1 in this sample).txis the transmit/receive bit — 0 means the BC is transmitting to the RT (BC-to-RT), 1 means the RT is transmitting to the BC (RT-to-BC).sais the subaddress.wcmcis the word count (or mode code for SA 0 and SA 31).
Command 0: Minor Frame Timer Gate
The first command block sets the minor frame period to 100,000 microseconds (100 ms). This is a timing-only command — it does not produce any bus traffic. The hardware uses this value to pace the schedule: after all messages in the frame complete, the BC waits until the frame timer expires before starting the next pass.
/* Load Minor Frame Timers to 100000 us (100 ms) */
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_LOAD_MINOR_FRAME_TIMER,1,1,0,0);
cmd1 = 0;
cmd2 = 0;
datablocknum = 0;
branchblock = 0;
timerus = 100000;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
Because this is a timer command and not a message, both command words (cmd1, cmd2) are zero and no data block is referenced.
Command 1: BC-to-RT Send (SA 2, 32 Words — Block A)
The first message command sends 32 words from the BC to RT address 1, subaddress 2. The control word uses EXEBLK_CONT so that execution continues to the next command block after this message completes. The command word sets tx=0, indicating a BC-to-RT direction.
/* BCRT Message with 32 words to RT SubAddress */
wordcnt = 32;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,0,rtsubaddr,wordcnt);
cmd2 = 0;
datablocknum = BLOCKA;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
for (i = 0; i < wordcnt; i++)
datablock[BLOCKA][i] = (uint16_t)(0xA000 + i);
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKA,datablock[BLOCKA]));
The data block is initialized with a recognizable pattern: word 0 = 0xA000, word 1 = 0xA001, and so on up to word 31 = 0xA01F. This makes it easy to verify correct transmission on the RT side. The data is loaded into Block A via naibrd_SUM1553_BC_LoadDataBlock().
Command 2: RT-to-BC Receive (SA 2, 32 Words — Block B)
The second message receives 32 words from RT address 1, subaddress 2. The command word sets tx=1, which flips the direction to RT-to-BC — the RT transmits and the BC receives into the specified data block.
/* RTBC Message with 32 words to RT SubAddress */
wordcnt = RTBC_WORDCNT;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,1,rtsubaddr,wordcnt);
cmd2 = 0;
datablocknum = BLOCKB;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
/* Writing to the BLOCKB datablock is not necessary. We initialize so we know that getting the RT transmit messages */
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKB][i] = (uint16_t)(0xB000 + i);
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKB,datablock[BLOCKB]));
Block B is pre-loaded with placeholder data (0xB000 + offset). This is not strictly required for a receive block — the hardware will overwrite it with actual RT response data. The placeholder values let the application distinguish "data received from the RT" from "initial placeholder still present," which is useful for verifying that the RT is responding.
Command 3: BC-to-RT Send (SA 3, 16 Words — Block C)
The third message sends 16 words from the BC to RT address 1, subaddress 3. Note the subaddress is rtsubaddr+1 (SA 3), differentiating this message from Command 1’s SA 2 target.
/* BCRT Message with 16 words to RT SubAddress */
wordcnt = 16;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,0,rtsubaddr+1,wordcnt);
cmd2 = 0;
datablocknum = BLOCKC;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
for (i = 0; i < wordcnt; i++)
datablock[BLOCKC][i] = (uint16_t)(0xC000 + i);
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKC,datablock[BLOCKC]));
Block C is initialized with the pattern 0xC000 through 0xC00F (16 words). Like Block A, this data can be updated at runtime by the interactive loop’s 'U' command.
Command 4: GOTO Block 0
The final command block is an unconditional branch back to command block 0. This creates the continuous loop: after all three messages execute, the hardware jumps back to the timer gate and begins the next minor frame.
/* Branch back to beginning of schedule */
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_GOTO,0,0,0,0);
cmd1 = 0;
cmd2 = 0;
datablocknum = 0;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
The GOTO control word uses retries=0, busa=0, and cond=0 because no bus transaction occurs — this is purely a flow-control instruction. The branchblock field is set to 0, directing execution back to the first command block (the timer gate).
|
Important
|
|
Starting Execution and Retrieving Results
Start
With all command blocks and data blocks loaded, two calls start the BC scheduler. First, set the command block pointer to the entry point of the schedule. Then enable execution:
/* Start with the first command */
check_status(naibrd_SUM1553_BC_SetCmdBlockPtr(cardIndex,module,bcchan,FIRST_CMD));
/* Run the BC */
check_status(naibrd_SUM1553_EnableExecution(cardIndex,module,bcchan,1));
The command block pointer must be set before enabling execution. The hardware needs to know which command block to begin with — if you enable execution without setting the pointer, the starting block is undefined and the schedule will not run correctly.
Retrieving RT-BC Results
After the scheduler is running, the application can read back the results of the RT-to-BC message (Block B) to see what the RT sent. The Retrieve_SUM1553_RTBCMessages() function handles this in two steps: first read the command block metadata, then read the received data.
static void Retrieve_SUM1553_RTBCMessages(int32_t cardIndex, int32_t module, int32_t bcchan)
{
uint16_t ctrl;
uint16_t cmd1, cmd2;
uint16_t status1, status2;
uint16_t branchblock;
uint32_t timerus;
uint16_t *dataptr = NULL;
uint16_t rxdatablock[32];
uint16_t rxwordcnt = RTBC_WORDCNT;
int32_t i;
check_status(naibrd_SUM1553_BC_ReadCmdBlock(cardIndex,module,bcchan,BLOCKB,&ctrl,&cmd1,&cmd2,dataptr,&status1,&status2,&branchblock,&timerus));
if ((ctrl & NAI_SUM1553_BC_CNTL_BAME) == 0)
{
/* Read the data from the RT */
naibrd_SUM1553_BC_ReadDataBlock(cardIndex,module,bcchan,BLOCKB,rxdatablock);
printf ("Status1=%04X Status2=%04X WordCnt = %d: Data=", status1, status2, rxwordcnt);
for (i=0; i < rxwordcnt; i++)
{
if (i != 0)
printf (",");
printf ("%04X", rxdatablock[i]);
}
printf("\n");
}
}
naibrd_SUM1553_BC_ReadCmdBlock() reads the command block for Block B and returns the control word, command words, status words, branch target, and timing fields. The control word is then checked for the BAME (Block Access Message Error) flag. If (ctrl & NAI_SUM1553_BC_CNTL_BAME) == 0, the message completed without error and it is safe to read the received data. naibrd_SUM1553_BC_ReadDataBlock() then reads the 32-word receive buffer from Block B into rxdatablock.
BAME and Status Bits
The control word returned by naibrd_SUM1553_BC_ReadCmdBlock() contains several status flags that indicate message outcome:
-
NAI_SUM1553_BC_CNTL_BAME(bit 0) — Block Access Message Error. Set when the message transaction failed (no RT response, wrong address or subaddress, bus error). -
NAI_SUM1553_BC_CNTL_SERVICE_REQUEST(bit 1) — the RT set the Service Request bit in its status word, indicating it has data or a condition that needs host attention. -
NAI_SUM1553_BC_CNTL_TERMINAL_FLAG(bit 4) — the RT set the Terminal Flag bit in its status word. -
NAI_SUM1553_BC_CNTL_BUSY_BIT(bit 5) — the RT responded with the Busy bit set, meaning it could not process the command at this time. -
NAI_SUM1553_BC_CNTL_MSG_ERROR(bit 6) — a message-level error occurred during the transaction.
Refer to the SUMMIT 1553 module manual for complete definitions of all control word status bits and their interactions with retry and conditional branching logic.
Stop
To halt the BC scheduler, disable execution by passing 0:
check_status(naibrd_SUM1553_EnableExecution(cardIndex,module,bcchan,0));
This stops the hardware from executing further command blocks. The schedule can be restarted later by setting the command block pointer and enabling execution again.
|
Important
|
|
Dynamic Data Updates
One of the key advantages of the SUM1553 BC architecture is that data blocks can be updated while the scheduler is running. naibrd_SUM1553_BC_LoadDataBlock() can be called at any time during execution — the hardware automatically picks up the new data on the next minor frame cycle. There is no need to stop and restart the scheduler.
Updating Transmit Data at Runtime
The Update_SUM1553_BCSAData() function demonstrates live data block updates. When the user presses 'U' in the interactive loop, the application increments a counter and reloads both Block A and Block C with new data patterns:
static void Update_SUM1553_BCSAData(int32_t cardIndex, int32_t module, int32_t bcchan, uint8_t increment)
{
int32_t wordcnt = 32;
uint8_t msb, lsb;
int32_t i;
msb = (uint8_t)(0xA0 | (increment & 0x0F)); /* upper byte (subaddress=upper 4 bits | increment=lower 4 bits)) */
lsb = 0;
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKA][i] = (msb << 8) | (uint8_t)(lsb + i); /* incremental data */
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKA,datablock[BLOCKA]));
msb = (uint8_t)(0xC0 | (increment & 0x0F)); /* upper byte (subaddress=upper 4 bits | increment=lower 4 bits)) */
lsb = 0;
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKC][i] = (msb << 8) | (uint8_t)(lsb + i); /* incremental data */
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKC,datablock[BLOCKC]));
}
Each press of 'U' advances the increment counter (lower 4 bits, cycling 0—15). Block A data is updated to the pattern (0xA0 | increment) << 8 | offset — for example, on the third press, word 0 = 0xA300, word 1 = 0xA301, and so on. Block C follows the same scheme with (0xC0 | increment) << 8 | offset. Both blocks are reloaded via naibrd_SUM1553_BC_LoadDataBlock() while the scheduler continues running uninterrupted.
When Dynamic Updates Are Useful
Live data block updates are valuable in any scenario where the BC transmit payload changes between cycles:
-
Real-time telemetry — sensor readings or system state that must be refreshed every frame.
-
Dynamic command payloads — command data that varies based on mission phase, operator input, or feedback from RTs.
-
Continuous data streaming — high-throughput applications where stopping the scheduler would cause unacceptable gaps in bus traffic.
Because the hardware picks up updated data on the very next cycle, there are zero missed cycles during an update.
Contrast with M1553 FTx BC Updates
On M1553 FTx modules, updating BC transmit data while the scheduler is running requires a stop-modify-restart sequence: call naibrd_1553_BcStop(), write the new data with naibrd_1553_BcDataBlockWrite(), and then call naibrd_1553_BcStart() to resume. This interruption means at least one minor frame is lost during every update.
SUM1553 eliminates this interruption entirely. naibrd_SUM1553_BC_LoadDataBlock() writes directly to the module’s data block memory while the scheduler continues executing. The hardware reads the data block at message transmission time, so an update that completes before the next cycle is guaranteed to take effect immediately.
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 SUM1553 Scheduled Message Failures
When a SUM1553 scheduled message fails, read the command block for the failed message using naibrd_SUM1553_BC_ReadCmdBlock() and check the BAME bit (bit 0 of the control word). If BAME is set, the message encountered an error — check the remaining status bits (MSG_ERROR, BUSY_BIT, TERMINAL_FLAG) for the specific cause. If BAME is clear but data looks wrong, verify the data block number matches between the command block configuration and your ReadDataBlock() call. Consult your module’s manual for complete status bit 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. If file doesn’t exist, configure and save from board menu. |
Module not recognized as SUMMIT 1553 |
Selected module is not N7/N8/NA/NB/NC. |
Verify module type at the selected slot. |
Reset not completing |
Hardware not responding after reset |
Verify module is powered and seated properly. |
Mode set failure |
Channel already in use or module doesn’t support BC mode |
Close other applications using this channel. |
Command block load failure |
Invalid block number or parameters |
Verify block number is within range (0-2047) and parameters are valid. |
Data block load failure |
Block number out of range |
Verify block number is within range (0-1023). |
Schedule not executing |
Command block pointer not set before enabling execution |
Call |
BAME set on every message |
RT not responding, wrong RT address or subaddress |
Verify RT is operational and address/subaddress match the schedule configuration. |
RT busy status |
RT cannot process commands at the scheduled rate |
Increase the minor frame timer period (currently 100,000 µs). |
No data in response block |
RT not configured with transmit data on the targeted subaddress |
Verify RT has data loaded for the subaddress the BC is requesting. |
Dynamic update not taking effect |
Wrong data block number in |
Verify the block number matches the command block’s data block reference (BLOCKA=0, BLOCKB=1, BLOCKC=2). |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — SUM1553_BC_Scheduler.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common 1553 Sample Program include files */
#include "nai_1553_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_sum1553.h"
static const int8_t *CONFIG_FILE = (int8_t *)"default_SUM1553_BCSched.txt";
/* Function prototypes */
static bool_t Run_SUM1553_BC_Scheduler(int32_t cardIndex, int32_t module, uint32_t modid);
static void Retrieve_SUM1553_RTBCMessages(int32_t cardIndex, int32_t module, int32_t bcchan);
static void Update_SUM1553_BCSAData(int32_t cardIndex, int32_t module, int32_t bcchan, uint8_t increment);
static const int32_t DEF_BC_CHANNEL = 2;
static const uint8_t DEF_RT_ADDR = 1;
static const uint8_t DEF_RT_SUBADDR = 2;
static const uint16_t RTBC_WORDCNT = 32;
static const uint16_t BLOCKA = 0;
static const uint16_t BLOCKB = 1;
static const uint16_t BLOCKC = 2;
static uint16_t datablock[3][32];
/**************************************************************************************************************/
/**
<summary>
The purpose of the SUM1553_BC_Scheduler is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Bus Controller and send and receive BC-RT and RT-BC scheduled messages.
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
Note, the SUM1553_BC_Scheduler can run in conjunction with the SUM1553_RT_PingPong or SUM1553_RT_ProcCtrl
applications to illustrate BC and RT operations together with the NAI 1553 module.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SUM1553_BC_Scheduler(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_SUM1553_BC_Scheduler(cardIndex, module, moduleID);
}
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
Run_SUM1553_BC_Scheduler queries the user for the module and channel to configure as the Bus Controller (BC).
After getting the module/channel selection, methods in the naibrd library are invoked to setup this channel
as a BC with the following scheduled predefined 1553 messages:
1) BC-RT message with 32 words of data to the "DEF_RT_ADDR" RT Address and "DEF_RT_SUBADDR" Subaddress
2) RT-BC message for 32 words of data to the "DEF_RT_ADDR" RT Address and "DEF_RT_SUBADDR" Subaddress
1) BC-RT message with 16 words of data to the "DEF_RT_ADDR" RT Address and "DEF_RT_SUBADDR+1" Subaddress
Once the BC is configured and running, the user can:
1) Type the Enter key to view the RT-BC response.
1) Type 'U' to change the data in the BC-RT message.
3) Type 'Q' to quit stop the BC execution and exit the routine.
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_SUM1553_BC_Scheduler(int32_t cardIndex, int32_t module, uint32_t modid)
{
bool_t bQuit;
bool_t bContinue = TRUE;
int32_t bcchan = 2;
const uint16_t FIRST_CMD = 0;
bool_t resetting;
uint32_t ncmd = 0;
int32_t wordcnt = 32;
uint8_t rtaddr = DEF_RT_ADDR;
uint8_t rtsubaddr = DEF_RT_SUBADDR;
uint16_t ctrl;
uint16_t cmd1, cmd2;
uint16_t datablocknum;
uint16_t branchblock;
uint32_t timerus;
uint8_t increment = 0;
int32_t i;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
bQuit = Get1553BCCfg(modid, DEF_BC_CHANNEL, &bcchan);
if (!bQuit)
{
/* Reset the channel */
check_status(naibrd_SUM1553_Reset(cardIndex,module,bcchan));
/* Wait for channels to reset */
while(check_status(naibrd_SUM1553_IsResetting(cardIndex,module,bcchan,&resetting)) == NAI_SUCCESS && resetting);
/* Setup the BC */
check_status(naibrd_SUM1553_SetMode(cardIndex,module,bcchan,NAI_SUM1553_OPSTATUS_BC_MODE)); /* Configure as BC */
/* Load commands */
ncmd = FIRST_CMD;
/* Load Minor Frame Timers to 100000 us (100 ms) */
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_LOAD_MINOR_FRAME_TIMER,1,1,0,0);
cmd1 = 0;
cmd2 = 0;
datablocknum = 0;
branchblock = 0;
timerus = 100000;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
/* BCRT Message with 32 words to RT SubAddress */
wordcnt = 32;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,0,rtsubaddr,wordcnt);
cmd2 = 0;
datablocknum = BLOCKA;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
for (i = 0; i < wordcnt; i++)
datablock[BLOCKA][i] = (uint16_t)(0xA000 + i);
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKA,datablock[BLOCKA]));
/* RTBC Message with 32 words to RT SubAddress */
wordcnt = RTBC_WORDCNT;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,1,rtsubaddr,wordcnt);
cmd2 = 0;
datablocknum = BLOCKB;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
/* Writing to the BLOCKB datablock is not necessary. We initialize so we know that getting the RT transmit messages */
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKB][i] = (uint16_t)(0xB000 + i);
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKB,datablock[BLOCKB]));
/* BCRT Message with 16 words to RT SubAddress */
wordcnt = 16;
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_EXEBLK_CONT,1,1,0,0);
cmd1 = NAI_SUM1553_COMMAND_WORD(rtaddr,0,rtsubaddr+1,wordcnt);
cmd2 = 0;
datablocknum = BLOCKC;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
for (i = 0; i < wordcnt; i++)
datablock[BLOCKC][i] = (uint16_t)(0xC000 + i);
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKC,datablock[BLOCKC]));
/* Branch back to beginning of schedule */
ctrl = NAI_SUM1553_BC_CTRL_WORD(NAI_SUM1553_OPCODE_GOTO,0,0,0,0);
cmd1 = 0;
cmd2 = 0;
datablocknum = 0;
branchblock = 0;
timerus = 0;
check_status(naibrd_SUM1553_BC_LoadCmdBlock(cardIndex,module,bcchan,ncmd++,ctrl,cmd1,cmd2,datablocknum,branchblock,timerus));
/* Start with the first command */
check_status(naibrd_SUM1553_BC_SetCmdBlockPtr(cardIndex,module,bcchan,FIRST_CMD));
/* Run the BC */
check_status(naibrd_SUM1553_EnableExecution(cardIndex,module,bcchan,1));
while (bContinue)
{
printf("\nType Enter key for RT-BC message, or U to update the subaddress transmit data or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (toupper(inputBuffer[0]) == 'U')
{
increment++;
Update_SUM1553_BCSAData(cardIndex,module,bcchan,increment);
}
else
{
Retrieve_SUM1553_RTBCMessages(cardIndex, module, bcchan);
}
}
else
bContinue = FALSE;
}
/* Disable the BC */
check_status(naibrd_SUM1553_EnableExecution(cardIndex,module,bcchan,0));
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
Retrieve_SUM1553_RTBCMessages reads the Command Block associated with the RT-BC message sent to the "DEF_RT_ADDR"
RT Address and "DEF_RT_SUBADDR" Subaddress. If the BAME (Block Access Message Error) bit is clear, indicating
no error, the Data block associated with the RT-BC message for RT Address and Subaddress is read.
</summary>
*/
/**************************************************************************************************************/
static void Retrieve_SUM1553_RTBCMessages(int32_t cardIndex, int32_t module, int32_t bcchan)
{
uint16_t ctrl;
uint16_t cmd1, cmd2;
uint16_t status1, status2;
uint16_t branchblock;
uint32_t timerus;
uint16_t *dataptr = NULL;
uint16_t rxdatablock[32];
uint16_t rxwordcnt = RTBC_WORDCNT;
int32_t i;
check_status(naibrd_SUM1553_BC_ReadCmdBlock(cardIndex,module,bcchan,BLOCKB,&ctrl,&cmd1,&cmd2,dataptr,&status1,&status2,&branchblock,&timerus));
if ((ctrl & NAI_SUM1553_BC_CNTL_BAME) == 0)
{
/* Read the data from the RT */
naibrd_SUM1553_BC_ReadDataBlock(cardIndex,module,bcchan,BLOCKB,rxdatablock);
printf ("Status1=%04X Status2=%04X WordCnt = %d: Data=", status1, status2, rxwordcnt);
for (i=0; i < rxwordcnt; i++)
{
if (i != 0)
printf (",");
printf ("%04X", rxdatablock[i]);
}
printf("\n");
}
}
/**************************************************************************************************************/
/**
<summary>
Update_SUM1553_BCSAData changes the data that is sent in the BC-RT messages sent to the "DEF_RT_ADDR"
RT Address and "DEF_RT_SUBADDR" and "DEF_RT_SUBADDR+1" Subaddresses.
</summary>
*/
/**************************************************************************************************************/
static void Update_SUM1553_BCSAData(int32_t cardIndex, int32_t module, int32_t bcchan, uint8_t increment)
{
int32_t wordcnt = 32;
uint8_t msb, lsb;
int32_t i;
msb = (uint8_t)(0xA0 | (increment & 0x0F)); /* upper byte (subaddress=upper 4 bits | increment=lower 4 bits)) */
lsb = 0;
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKA][i] = (msb << 8) | (uint8_t)(lsb + i); /* incremental data */
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKA,datablock[BLOCKA]));
msb = (uint8_t)(0xC0 | (increment & 0x0F)); /* upper byte (subaddress=upper 4 bits | increment=lower 4 bits)) */
lsb = 0;
for (i = 0; i < wordcnt; i++)
{
datablock[BLOCKC][i] = (msb << 8) | (uint8_t)(lsb + i); /* incremental data */
}
check_status(naibrd_SUM1553_BC_LoadDataBlock(cardIndex,module,bcchan,BLOCKC,datablock[BLOCKC]));
}
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;
}