MIL-STD-1553 & 1760 Family Guide

Overview

The FT family is NAI’s line of MIL-STD-1553 and MIL-STD-1760 communication modules. 1553 is a command/response, time-division-multiplexed bus run by a single Bus Controller (BC) — nothing talks unless the BC tells it to. The BC issues commands; up to 31 Remote Terminals (RTs) respond only when addressed; a Bus Monitor (MT) listens without participating. That’s the opposite of CAN’s broadcast free-for-all and different from ARINC’s one-way labeled words — on 1553, one controller orchestrates every transfer.

In a real system, 1553 is the command/response data backbone of military avionics — the deterministic, dual-redundant bus tying a platform’s mission computer to its subsystems (radar, navigation, displays, flight control, weapons management) on aircraft, helicopters, ships, and spacecraft. MIL-STD-1760 is the aircraft-to-store interface layered on that bus: its data link is a 1553 bus, plus the power, safety interlocks, and connector a weapons station needs — so a compliant weapon plugs into a compliant aircraft and talks over 1553. In this family, FTA–FTF are general-purpose 1553 modules and FTJ/FTK are 1760 modules; both share the same naibrd_1553_* API and dual-redundant bus (see 1553 vs 1760 for the full comparison).

This page is the starting point for any FT module — understand the family, pick a member, wire it onto a bus, confirm a channel, and run your first BC↔RT exchange. (Related NAI avionics-bus families: AR for ARINC 429/575, CB for CANbus.)

For a short visual introduction, watch this overview:

FT modules at a glance

Every FT module is a dual-redundant 1553-bus interface whose channels can each be a Bus Controller, Remote Terminal, Bus Monitor, or combined RT/BM, built on the Sital BRM1553D core (DDC® Enhanced Mini-ACE® register-compatible). They split into two groups by standard:

MIL-STD-1553 (general avionics data bus):

ModuleCouplingDual-redundant channels
FTA / FTB / FTCTransformer-coupled1, 2, or 4 (model-specific)
FTD / FTE / FTFDirect-coupled1, 2, or 4 (model-specific)

FTA–FTF run NAI’s Assisted Mode (an onboard ARM processor offloads message movement from your host CPU) with 16K words of memory per channel.

MIL-STD-1760 (aircraft/store interface, built on a 1553 bus):

ModuleCouplingChannelsNotable
FTJTransformer-coupled11760 store interface — see 1760 features below
FTKTransformer-coupled2Same, dual-channel

FTJ/FTK are primarily Remote Terminals (a store is an RT to the aircraft’s BC); their 1760-specific hardware is detailed in 1553 vs 1760 and Features.

Note

The exact channel count per FTA–FTF model — which of FTA/FTB/FTC and FTD/FTE/FTF is the 1-, 2-, or 4-channel variant — is on the FTA-FTF data sheet and should be confirmed before finalizing that table. (FTJ = 1 channel and FTK = 2 channels are confirmed from the FTJ-FTK manual.)

Choosing a member:

  • General 1553 data bus — connecting an NAI system to a standard 1553 bus as BC, RT, or monitor — FTA–FTF. Pick transformer-coupled (FTA/FTB/FTC) for a normal bus (isolated, longer stub) or direct-coupled (FTD/FTE/FTF) for short, point-to-point/bench links; pick the 1- / 2- / 4-channel variant for how many buses you run.
  • Aircraft/store (weapons) interface — when you need MIL-STD-1760 compliance: EEPROM auto-init RT, power-on response timing, hardwired RT address, interlock — FTJ (1 channel) or FTK (2 channels).
  • A self-test loopback needs two channels on the module — so use a 2-/4-channel FTA–FTF or the dual-channel FTK for that.

Combination modules that include MIL-STD-1553:

ModuleCombinesManual
CM5MIL-STD-1553 + ARINC 429CM5 Manual
CM8MIL-STD-1553 + Discrete I/OCM8 Manual

NAI systems like the CIU3 also include an inboard 1553 channel (inside the IF2 combination function). The naibrd_1553_* API is the same across all of them.

1553 vs 1760 — how they relate

Because this guide covers both, it’s worth being precise about the relationship:

MIL-STD-1553 (FTA–FTF)MIL-STD-1760 (FTJ/FTK)
What it isA digital data bus standardAn aircraft-to-store electrical interface standard (AEIS)
Data linkThe 1553 bus itselfUses a 1553 bus as its data link
Adds on top of 1553Tighter signal tolerances, power-on response timing, hardwired RT address + parity, interlock/discretes, power & connector specs
Typical roleBC, RT, or monitor — generalPrimarily RT (the store responds to the aircraft’s BC)
CouplingTransformer or directTransformer only
Transceiver / memoryStandard 1553, 16K words/chHolt-6130, 64K words/ch
APInaibrd_1553_*Same naibrd_1553_*, plus EEPROM/1760 extras

The short version: 1553 is the language; 1760 is the whole standardized “docking port” between an aircraft and a weapon — power, safety interlocks, the connector, and a 1553 data link for talking. FTJ/FTK implement that 1553 data link with the extra hardware 1760 requires. Everything in the rest of this guide about BC/RT/MT, the bus, and the API applies to both groups; the 1760-only extras are called out where relevant.

Physical setup

A 1553 bus is a shielded, twisted-pair running Manchester-II at 1 Mbit/s, and it is dual-redundant — there are two independent buses, the primary “A” bus and the secondary “B” bus. Terminals are wired to both; a message is normally sent on one bus at a time, and devices accept traffic on either with equal priority. Two physical-layer rules matter most:

  • Both ends of each bus must be terminated — with a resistor equal to the cable’s characteristic impedance (70–85 Ω) within ±2% (nominally ~78 Ω). 1553 buses are terminated at the two far ends of the main cable, not at every stub.
  • Stub length depends on coupling. A transformer-coupled terminal may sit up to 20 ft from the main bus; a direct-coupled terminal must be within 1 ft. Use the coupling that matches your module (FTA/B/C and FTJ/FTK transformer; FTD/E/F direct).

The exact connector pins are per-module, so get them from the manual; the pattern is the same:

  1. Identify the module’s slot number on your NAI motherboard or system.
  2. Bring the channel’s bus signals out through the breakout board, where the slot’s pins appear as generic IO# numbers.
  3. Map IO# pins to each channel’s Bus A and Bus B pairs — by the pinout in the module’s manual (or FTJ-FTK Manual for 1760) or the module’s overlay card.
  4. Wire the channel onto the bus (A and B) through the appropriate coupling, with the bus terminated at both ends.

A few things hold for the family:

  • One bus, one controller. Exactly one terminal on a 1553 bus is the Bus Controller at a time; everything else is an RT or a monitor. The BC initiates every transfer.
  • RT address identifies the terminal. Each RT has a 5-bit address (0–30; 31 is the broadcast address). On FTA–FTF the RT address can be set from discrete pins or in software (the discrete pins are shared per channel-pair — the even channel is a hard “+1” offset from the odd channel’s pin pattern). On FTJ/FTK (1760) each channel has its own hardwired set of 5 binary-weighted address lines + a parity line + common return, checked for odd parity and latched on boot/reset — that’s how an aircraft pylon assigns a store its address.
  • BC_DISABLE / M1760 pins. A channel comes up as a BC only when its external BC_DISABLE (and M1760) pins are driven appropriately. On a bench where those pins aren’t wired, the SSK lets you software-override them so the channel can act as BC (see the self-test below).
  • 1760 adds more than data. Beyond the 1553 bus, FTJ/FTK provide an Interlock / Interlock-RTN low-impedance continuity path and expect 1760 discrete signals to be handled per the aircraft’s safety requirements. And 1760 imposes power-on response timing (below) that’s a system-integration concern, not just a wiring one.

Two worked examples (use your module’s pinout for the actual pins):

  • Join a real bus as a Remote Terminal. Wire the channel’s Bus A (and Bus B) onto the existing bus through the right coupling, set the channel to RT mode with the address your BC expects (hardwired on FTJ/FTK), and the module responds when addressed. Don’t re-terminate the bus — it’s already terminated at its two ends.
  • Bench BC↔RT loopback across two channels. Cable channel 1 to channel 2 on the same module over a short, terminated bus, make channel 1 the BC and channel 2 an RT — the BC sends and the RT receives. That’s exactly the self-test below.

Software

There’s nothing 1553/1760-specific about which software you run. The NAI SSK (naibrd library) is identical across every OS and architecture — PetaLinux, VxWorks, DEOS, Windows. What OS you’re on is determined by your motherboard/SBC, not by the FT module. The only family-specific part is which API functions you call: every FT module — 1553 and 1760 — uses the naibrd_1553_* calls.

Every 1553 channel follows the same lifecycle regardless of role: open the channel and bind it to a logical device number, initialize it in the role you want, do work, then free it. The SSK 1.x and SSK 2.x APIs do the same thing with slightly different names — pick your version below:

/* SSK 1.x */
naibrd_1553_Open(cardIndex, module, channel, devnum);                /* bind channel -> logical device */
naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD,
                       NAI_1553_MODE_BC, 0, 0, 0);                    /* role: _MODE_BC / _MODE_RT / _MODE_MT */
/* ... do BC / RT / MT work ... */
naibrd_1553_Free(devnum);
/* SSK 2.x */
naibrd_1553_Open(cardIndex, module, channel, devnum);                /* bind channel -> logical device */
naibrd_1553_Init(devnum, NAIBRD_1553_ACCESS_CARD,
                NAIBRD_1553_MODE_BC, 0, 0, 0);                        /* role: _MODE_BC / _MODE_RT / _MODE_MT */
/* ... do BC / RT / MT work ... */
naibrd_1553_Free(devnum);

The role you pass to the init call — NAIBRD_1553_MODE_BC / NAI_1553_MODE_BC (or _MODE_RT, _MODE_MT) — determines which family of calls you use next. Where to find what you need:

  • Which functions/registers to call — the FTA-FTF Manual (1553) and FTJ-FTK Manual (1760) document the registers and the full naibrd_1553_* API (BC frame building, RT command stack, monitor, mode codes, EEPROM, status, BIT). Because the core is DDC Mini-ACE-compatible, DDC users will find the register model familiar.
  • Building and deploying on your platformConnecting to Boards covers the toolchain, deployment, and terminal access for PetaLinux/ARM Linux, VxWorks, DEOS, and Windows.
  • Launching the app on the board itselfRunning Applications from the Target walks through loading and launching your executable on the target.

Example — a 68ARM2 SBC with an FTA module: pull the naibrd_1553_* calls from the FTA-FTF Manual, set up the ARM Linux toolchain per Connecting to Boards, then load and launch a 1553 sample on the target per Running Applications from the Target.

Confirm communication

Because 1553 is a controlled bus, the self-test is a two-channel external loopback: make one channel the Bus Controller and another channel a Remote Terminal, cable them together on a short terminated bus, have the BC send a message, and confirm the RT receives it and the BC sees the RT’s response. (1553 has no zero-wiring internal self-test like CAN’s BIT — proving the bus needs two channels and cabling. The FT modules do expose a BIT status register you can read once running; see the next section.)

Wire it: cable channel 1’s bus to channel 2’s bus (Bus A is enough for a bench test), terminated at both ends. This needs a module with two channels (an FTK, or a 2-/4-channel FTA–FTF).

Set it up: open both channels, initialize channel 1 as NAIBRD_1553_MODE_BC and channel 2 as NAIBRD_1553_MODE_RT. On a bench, the BC channel’s BC_DISABLE/M1760 pins usually aren’t driven, so enable the software override (via naibrd_1553_WriteAuxRegister) so the channel is allowed to act as BC. Then the BC sends a BC-to-RT message and you read the result on both ends.

If the words the BC sent show up at the RT — and the BC’s decoded response shows the RT’s status word with no error bits — your board connection, the SSK, the module, and your bus wiring/termination are all confirmed. The m1553_ext_loopback_fifo sample does exactly this: it configures one channel as BC and another as RT on the same module, sends a message, and displays both decoded results side by side.

Features

Everything you do with an FT module happens per channel, and each channel is a complete, independent 1553 interface — a 4-channel module is effectively four separate 1553 nodes in one package, each with its own dual-redundant A and B bus and its own memory (16K words/channel on FTA–FTF, 64K on FTJ/FTK). Channels run independently and at the same time, and each picks its own role: one module can have channel 1 as a BC commanding channel 2 set up as an RT (exactly what the loopback self-test does), while a third channel monitors.

In software you bind a physical channel to a logical device number with naibrd_1553_Open(cardIndex, module, channel, devnum), then address it by devnum for everything after; the init call sets the channel’s role and the free call releases it (the full lifecycle is in Software above).

Every function starts from the standard connection flow (naiapp_RunBoardMenu()naiapp_query_CardIndex() / naiapp_query_ModuleNumber()cardIndex/module/channel; see Opening a Software Handle to Your Board). The role you pass to the init call (_MODE_BC / _MODE_RT / _MODE_MT) decides which feature below applies — and as a rule of thumb, 1553 (FTA–FTF) channels are general-purpose (BC/RT/monitor) while 1760 (FTJ/FTK) channels are primarily RTs. Think of these like ESP2’s tabs: each is a thing you can make a channel do.

Each feature below lists a sampling of the relevant naibrd_1553_* calls; for the workflow order, see Try it further down. Full signatures and parameters are in the FTA-FTF Manual and FTJ-FTK Manual.

Bus Controller (BC) — run the bus and send messages

What it does / when: the BC initiates every transfer on the bus. Use it to command RTs, or to simulate the mission computer when testing other avionics. A BC doesn’t just send bytes — it runs a small schedule built bottom-up: data block → message → minor frame → major frame → start → decode.

Applies to: any FT channel. (Bench note: a BC channel needs its BC_DISABLE/M1760 pins driven or software-overridden — see Confirm communication.)

Also on the BC: scheduling (repeating timed frames), asynchronous injection into a running schedule, a configurable message-retry policy, all four message types plus mode codes (Synchronize, Transmit Status Word, Dynamic Bus Control, …), and — FTA–FTF only — high-throughput Message FIFO mode.

Relevant APIs:

/* SSK 1.x */
nai_1553_t naibrd_1553_BcDataBlockCreate(int16_t swDevice, int16_t swDataBlockId, uint16_t wDataBlockSize, uint16_t* wapBuffer, uint16_t wBufferSize);
nai_1553_t naibrd_1553_BcDataBlockWrite(int16_t swDevice, int16_t swDataBlockId, uint16_t* wapBuffer, uint16_t wBufferSize, uint16_t wOffset);
nai_1553_t naibrd_1553_BcMessageCreateBcToRt(int16_t swDevice, int16_t swMessageId, int16_t swDataBlockId, uint16_t wReceiverRt, uint16_t wReceiverRtSubaddress, uint16_t wWordCount, uint16_t wGapTime, uint32_t dwOptions);
nai_1553_t naibrd_1553_BcMessageCreateRtToBc(int16_t swDevice, int16_t swMessageId, int16_t swDataBlockId, uint16_t wTransmitterRt, uint16_t wTransmitterRtSubaddress, uint16_t wWordCount, uint16_t wGapTime, uint32_t dwOptions);
nai_1553_t naibrd_1553_BcMessageCreateRtToRt(int16_t swDevice, int16_t swMessageId, int16_t swDataBlockId, uint16_t wReceiverRt, uint16_t wReceiverRtSubaddress, uint16_t wWordCount, uint16_t wTransmitterRt, uint16_t wTransmitterRtSubaddress, uint16_t wGapTime, uint32_t dwOptions);
nai_1553_t naibrd_1553_BcMessageCreateMode(int16_t swDevice, int16_t swMessageId, int16_t swDataBlockId, uint16_t wRt, uint16_t wMessageDirection, uint16_t wModeCommand, uint16_t wGapTime, uint32_t dwOptions);
nai_1553_t naibrd_1553_BcCommandCreate(int16_t swDevice, int16_t swCommandId, uint16_t wOpcode, uint16_t wCondition, uint32_t dwParameter1, uint32_t dwParameter2, uint32_t dwReserved);
nai_1553_t naibrd_1553_BcFrameCreate(int16_t swDevice, int16_t swFrameId, uint16_t wFrameType, int16_t* swapCommandIds, uint16_t wCommandCount, uint16_t wFrameTime, uint16_t wFlags);
nai_1553_t naibrd_1553_BcStart(int16_t swDevice, int16_t swFrameId, int32_t sdwFrameCount);
nai_1553_t naibrd_1553_BcStop(int16_t swDevice);
nai_1553_t naibrd_1553_BcMessageGetByIdDecoded(int16_t swDevice, int16_t swMessageId, naiDecodedMessageStructure* dmspDecodedMessage, uint16_t wIsPurgeRequired);
nai_1553_t naibrd_1553_WriteAuxReg(int16_t swDevice, uint32_t wAuxRegisterAddress, uint16_t wAuxRegisterValue);
/* SSK 2.x */
naibrd_1553_t naibrd_1553_BcDataBlkCreate(int16_t device, int16_t dataBlockId, naibrd_1553_bc_dataBlockSize_t dataBlockSize, const uint16_t* p_buffer, uint16_t writeCount);
naibrd_1553_t naibrd_1553_BcDataBlkWrite(int16_t device, int16_t dataBlockId, const uint16_t* p_buffer, uint16_t writeCount, uint16_t offset);
naibrd_1553_t naibrd_1553_BcMsgCreateBcToRt(int16_t device, int16_t messageId, int16_t dataBlockId, naibrd_1553_rt_address_t receiverRt, naibrd_1553_rt_subaddress_t receiverRtSubaddress, uint16_t wordCount, uint16_t gapTime_uS, naibrd_1553_bc_msg_options_t bcMsgOptions);
naibrd_1553_t naibrd_1553_BcMsgCreateRtToBc(int16_t device, int16_t messageId, int16_t dataBlockId, naibrd_1553_rt_address_t transmitterRt, naibrd_1553_rt_subaddress_t transmitterRtSubaddress, uint16_t wordCount, uint16_t gapTime_uS, naibrd_1553_bc_msg_options_t bcMsgOptions);
naibrd_1553_t naibrd_1553_BcMsgCreateRtToRt(int16_t device, int16_t messageId, int16_t dataBlockId, naibrd_1553_rt_address_t receiverRt, naibrd_1553_rt_subaddress_t receiverRtSubaddress, uint16_t wordCount, naibrd_1553_rt_address_t transmitterRt, naibrd_1553_rt_subaddress_t transmitterRtSubaddress, uint16_t gapTime_uS, naibrd_1553_bc_msg_options_t bcMsgOptions);
naibrd_1553_t naibrd_1553_BcMsgCreateMode(int16_t device, int16_t messageId, int16_t dataBlockId, naibrd_1553_rt_address_t rt, naibrd_1553_messageDirection_t messageDirection, naibrd_1553_bc_mode_commands_t modeCommand, uint16_t gapTime_uS, naibrd_1553_bc_msg_options_t bcMsgOptions);
naibrd_1553_t naibrd_1553_BcCmdCreate(int16_t device, int16_t commandId, naibrd_1553_bc_opcode_t opcode, naibrd_1553_bc_condition_t condition, uint32_t parameter1, uint32_t parameter2, uint32_t reserved);
naibrd_1553_t naibrd_1553_BcFrmCreate(int16_t device, int16_t frameId, naibrd_1553_bc_frameType_t frameType, const int16_t* p_commandIdBuffer, uint16_t commandCount, uint16_t frameTime, naibrd_1553_bc_frameoptions_t flags);
naibrd_1553_t naibrd_1553_BcStart(int16_t device, int16_t frameId, int32_t frameCount);
naibrd_1553_t naibrd_1553_BcStop(int16_t device);
naibrd_1553_t naibrd_1553_BcMsgGetByIdDecoded(int16_t device, int16_t messageId, naibrd_1553_msgstruct_t* p_outdecodedMessage, uint16_t isPurgeRequired);
naibrd_1553_t naibrd_1553_WriteAuxRegister(int16_t device, naibrd_1553_general_auxRegAddress_t auxRegisterAddress, naibrd_1553_aux_reg_value_t auxRegisterValue);

Exercise it: BC Send Message (start here) · BC Run Schedule · BC Async · BC FIFO (FTA–FTF) · ESP2 “BC” tab.

Remote Terminal (RT) — respond when addressed

What it does / when: an RT waits passively and answers only when the BC addresses it. Use it to simulate a subsystem/sensor, or to be the actual store on a 1760 module.

Applies to: any FT channel; the primary role for FTJ/FTK.

Also on the RT: legalize the subaddresses it answers (Tx/Rx/Broadcast), read incoming messages off the command stack, and stage outgoing data double-buffered. FTA–FTF also offer RT FIFO mode.

Relevant APIs:

/* SSK 1.x */
nai_1553_t naibrd_1553_RtSetAddress(int16_t swDevice, uint16_t wRtAddress);
nai_1553_t naibrd_1553_RtGetAddress(int16_t swDevice, uint16_t* wpRtAddress);
nai_1553_t naibrd_1553_RtSetAddressSource(int16_t swDevice, uint16_t wRtAddressSource);
nai_1553_t naibrd_1553_RtDataBlockCreate(int16_t swDevice, int16_t swDataBlockId, uint16_t wDataBlockType, uint16_t* wapBuffer, uint16_t wBufferSize);
nai_1553_t naibrd_1553_RtDataBlockMapToSubaddress(int16_t swDevice, int16_t swDataBlockId, uint16_t wSubaddress, uint16_t wMessageTypes, uint16_t wIrqOptions, uint16_t bIsSubaddressLegalizationRequested);
nai_1553_t naibrd_1553_RtDataBlockWrite(int16_t swDevice, int16_t swDataBlockId, uint16_t* wapBuffer, uint16_t wBufferSize, uint16_t wOffset);
nai_1553_t naibrd_1553_RtTxDataBlockSwap(int16_t swDevice, int16_t swDataBlockId, uint16_t wSubaddress);
nai_1553_t naibrd_1553_RtMessageGetFromStackRaw(int16_t swDevice, uint16_t* wapBuffer, uint16_t wBufferSize);
nai_1553_t naibrd_1553_RtMessageDecodeRaw(int16_t swDevice, uint16_t* wapBuffer, naiDecodedMessageStructure* dmspDecodedMessage);
nai_1553_t naibrd_1553_RtStart(int16_t swDevice);
nai_1553_t naibrd_1553_RtStop(int16_t swDevice);
/* SSK 2.x */
naibrd_1553_t naibrd_1553_RtSetAddr(int16_t device, naibrd_1553_rt_address_t rtAddress);
naibrd_1553_t naibrd_1553_RtGetAddr(int16_t device, naibrd_1553_rt_address_t* p_outrtAddress);
naibrd_1553_t naibrd_1553_RtSetAddrSrc(int16_t device, naibrd_1553_rt_rtAddressSource_t rtAddressSource);
naibrd_1553_t naibrd_1553_RtDataBlkCreate(int16_t device, int16_t dataBlockId, naibrd_1553_rt_dataBlockType_t dataBlockType, const uint16_t* p_buffer, uint16_t writeCount);
naibrd_1553_t naibrd_1553_RtDataBlkMapToSA(int16_t device, int16_t dataBlockId, naibrd_1553_rt_subaddress_t subaddress, naibrd_1553_rt_messageTypes_t messageTypes, naibrd_1553_rt_irqOptions_t irqOptions, uint16_t isSubaddressLegalizationRequested);
naibrd_1553_t naibrd_1553_RtDataBlkWrite(int16_t device, int16_t dataBlockId, const uint16_t* p_buffer, uint16_t writeCount, uint16_t offset);
naibrd_1553_t naibrd_1553_RtTxDataBlkSwap(int16_t device, int16_t dataBlockId, naibrd_1553_rt_subaddress_t subaddress);
naibrd_1553_t naibrd_1553_RtMsgGetFromStackRaw(int16_t device, uint16_t* p_outbuffer, uint16_t bufferLength);
naibrd_1553_t naibrd_1553_RtMsgDecodeRaw(int16_t device, const uint16_t* p_buffer, naibrd_1553_msgstruct_t* p_outdecodedMessage);
naibrd_1553_t naibrd_1553_RtStart(int16_t device);
naibrd_1553_t naibrd_1553_RtStop(int16_t device);

Exercise it: RT Receive · RT Status Bits · RT Receive FIFO (FTA–FTF) · ESP2 “RT” tab.

Bus Monitor (MT) — passively capture traffic

What it does / when: records every message on the bus without transmitting — for analysis, debugging, and recording during integration/flight test. A channel can also run combined RT/BM.

Applies to: any FT channel. FTA–FTF add a FIFO monitor mode.

Relevant APIs:

/* SSK 1.x */
nai_1553_t naibrd_1553_MtMessageMonitoringDisable(int16_t swDevice, uint16_t wRtAddress, uint16_t wMessageDirection, uint32_t dwRtSubaddressMask);
nai_1553_t naibrd_1553_MtStart(int16_t swDevice);
nai_1553_t naibrd_1553_MtStop(int16_t swDevice);
nai_1553_t naibrd_1553_MtMessageGetFromStackRaw(int16_t swDevice, uint16_t* wapBuffer, uint16_t wBufferSize, uint16_t wStackSelector);
nai_1553_t naibrd_1553_MtMessageDecodeRaw(int16_t swDevice, uint16_t* wapBuffer, naiDecodedMessageStructure* dmspDecodedMessage);
/* SSK 2.x */
naibrd_1553_t naibrd_1553_MtMsgMonitoringDisable(int16_t device, uint16_t rtAddress, naibrd_1553_messageDirection_t messageDirection, naibrd_1553_rt_subaddress_mask_t rtSubaddressMask);
naibrd_1553_t naibrd_1553_MtStart(int16_t device);
naibrd_1553_t naibrd_1553_MtStop(int16_t device);
naibrd_1553_t naibrd_1553_MtMsgGetFromStackRaw(int16_t device, uint16_t* p_outBuffer, uint16_t bufferSize, naibrd_1553_mt_stack_selector_t stackSelector);
naibrd_1553_t naibrd_1553_MtMsgDecodeRaw(int16_t device, const uint16_t* p_buffer, naibrd_1553_msgstruct_t* p_outdecodedMessage);

Exercise it: MT Monitor · MT Monitor FIFO (FTA–FTF).

1760 store operation (FTJ/FTK only) — EEPROM auto-init

What it does / when: set up a store that powers up already responding as a configured RT within the MIL-STD-1760 timing, with no host intervention — its legalized subaddresses and per-subaddress data are restored from EEPROM on power-up.

Applies to: FTJ / FTK only.

Also on 1760: configure the channel as an RT first (legalize subaddresses, write the initial data), then unlock and copy the configuration to EEPROM. The hardwired RT address, power-on response timing, and interlock are described under Hardware capabilities and status monitoring.

Relevant APIs:

/* SSK 1.x */
nai_1553_t naibrd_1553_RtGetAddress(int16_t swDevice, uint16_t* wpRtAddress);
nai_1553_t naibrd_1553_RtDataBlockCreate(int16_t swDevice, int16_t swDataBlockId, uint16_t wDataBlockType, uint16_t* wapBuffer, uint16_t wBufferSize);
nai_1553_t naibrd_1553_RtDataBlockMapToSubaddress(int16_t swDevice, int16_t swDataBlockId, uint16_t wSubaddress, uint16_t wMessageTypes, uint16_t wIrqOptions, uint16_t bIsSubaddressLegalizationRequested);
nai_1553_t naibrd_1553_RtDataBlockWrite(int16_t swDevice, int16_t swDataBlockId, uint16_t* wapBuffer, uint16_t wBufferSize, uint16_t wOffset);
nai_1553_t naibrd_1553_RtStart(int16_t swDevice);
nai_1760_t naibrd_1760_SetEEPROMUnlock(int16_t swDevice);
nai_1760_t naibrd_1760_SetEECOPY(int16_t swDevice, bool_t assert);
nai_1760_t naibrd_1760_GetDeviceReady(int16_t swDevice, bool_t* ready);
/* SSK 2.x */
naibrd_1553_t naibrd_1553_RtGetAddr(int16_t device, naibrd_1553_rt_address_t* p_outrtAddress);
naibrd_1553_t naibrd_1553_RtDataBlkCreate(int16_t device, int16_t dataBlockId, naibrd_1553_rt_dataBlockType_t dataBlockType, const uint16_t* p_buffer, uint16_t writeCount);
naibrd_1553_t naibrd_1553_RtDataBlkMapToSA(int16_t device, int16_t dataBlockId, naibrd_1553_rt_subaddress_t subaddress, naibrd_1553_rt_messageTypes_t messageTypes, naibrd_1553_rt_irqOptions_t irqOptions, uint16_t isSubaddressLegalizationRequested);
naibrd_1553_t naibrd_1553_RtDataBlkWrite(int16_t device, int16_t dataBlockId, const uint16_t* p_buffer, uint16_t writeCount, uint16_t offset);
naibrd_1553_t naibrd_1553_RtStart(int16_t device);
naibrd_1760_t naibrd_1760_SetEEPROMUnlock(int16_t swDevice);
naibrd_1760_t naibrd_1760_SetEECOPY(int16_t swDevice, bool_t assert);
naibrd_1760_t naibrd_1760_GetDeviceReady(int16_t swDevice, bool_t* ready);

Exercise it: 1760 RT Program EEPROM (build a specific RT config and save it) · 1760 EEPROM Copy (copy current state).

Self-test (loopback)

To confirm a channel end-to-end, run a two-channel BC↔RT external loopback — covered conceptually under Confirm communication and shown as worked code in Try it — Bus Controller and Try it — Remote Terminal below. The External Loopback sample implements the full version.

Try it

The snippets below show the order of naibrd_1553_* calls you’d make for each role — drop them into the body of an NAI sample app (after the standard connection flow described in Software above) and you have a working test. Each snippet is the conceptual sequence — not a fully-buildable program — and the corresponding SSK sample applications under each role’s “Exercise it:” line above are the full reference.

Try it — Bus Controller

A minimal BC sends a single BC-to-RT message and reads the decoded response. The frame hierarchy goes data block → message → command → minor frame → major frame, then start.

/* SSK 1.x — Bus Controller (single BC-to-RT message) */
naibrd_1553_Open(cardIndex, module, channel, devnum);
/* Bench override of BC_DISABLE/M1760 so the channel is allowed to be BC */
naibrd_1553_WriteAuxReg(devnum, 0x2, 0xA000);
naibrd_1553_WriteAuxReg(devnum, 0x1, 0x1);
naibrd_1553_WriteAuxReg(devnum, 0x1, 0x0);
naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_BC, 0, 0, 0);
 
/* Build the frame: data block -> message -> command -> minor -> major */
naibrd_1553_BcDataBlockCreate(devnum, DBLK, WORDCOUNT, NULL, 0);
naibrd_1553_BcMessageCreateBcToRt(devnum, MSG, DBLK, RT_ADDR, RT_SA, WORDCOUNT, 0, BUS);
naibrd_1553_BcCommandCreate(devnum, OP, NAI_1553_OPCODE_EXECUTE_MESSAGE,
                            NAI_1553_OPCODE_COND_ALWAYS, MSG, 0, 0);
naibrd_1553_BcFrameCreate(devnum, MNR, NAI_1553_BC_FRAME_MINOR, opcodes, 1, 0, 0);
naibrd_1553_BcFrameCreate(devnum, MJR, NAI_1553_BC_FRAME_MAJOR, opcodes, 1, 1000, 0);
 
/* Send and read the decoded result */
naibrd_1553_BcDataBlockWrite(devnum, DBLK, data, WORDCOUNT, 0);
naibrd_1553_BcStart(devnum, MJR, 1);
naibrd_1553_BcMessageGetByIdDecoded(devnum, MSG, &decoded, 1);
naibrd_1553_BcStop(devnum);
naibrd_1553_Free(devnum);
/* SSK 2.x — Bus Controller (single BC-to-RT message) */
naibrd_1553_Open(cardIndex, module, channel, devnum);
/* Bench override of BC_DISABLE/M1760 so the channel is allowed to be BC */
naibrd_1553_WriteAuxRegister(devnum, NAIBRD_1553_AUX_ADDRESS_MISC_BITS, 0xA000);
naibrd_1553_WriteAuxRegister(devnum, NAIBRD_1553_AUX_ADDRESS_RESET, 1);
naibrd_1553_WriteAuxRegister(devnum, NAIBRD_1553_AUX_ADDRESS_RESET, 0);
naibrd_1553_Init(devnum, NAIBRD_1553_ACCESS_CARD, NAIBRD_1553_MODE_BC, 0, 0, 0);
 
/* Build the frame: data block -> message -> command -> minor -> major */
naibrd_1553_BcDataBlkCreate(devnum, DBLK, WORDCOUNT, NULL, 0);
naibrd_1553_BcMsgCreateBcToRt(devnum, MSG, DBLK, RT_ADDR, RT_SA, WORDCOUNT, 0, BUS);
naibrd_1553_BcCmdCreate(devnum, OP, NAIBRD_1553_OPCODE_EXECUTE_MESSAGE,
                       NAIBRD_1553_OPCODE_COND_ALWAYS, MSG, 0, 0);
naibrd_1553_BcFrmCreate(devnum, MNR, NAIBRD_1553_BC_FRAME_MINOR,
                       opcodes, 1, 0, NAIBRD_1553_BC_FRAME_DEFAULT);
naibrd_1553_BcFrmCreate(devnum, MJR, NAIBRD_1553_BC_FRAME_MAJOR,
                       opcodes, 1, 1000, NAIBRD_1553_BC_FRAME_DEFAULT);
 
/* Send and read the decoded result */
naibrd_1553_BcDataBlkWrite(devnum, DBLK, data, WORDCOUNT, 0);
naibrd_1553_BcStart(devnum, MJR, 1);
naibrd_1553_BcMsgGetByIdDecoded(devnum, MSG, &decoded, 1);
naibrd_1553_BcStop(devnum);
naibrd_1553_Free(devnum);

Try it — Remote Terminal

An RT sets its address, legalizes the subaddresses it answers, stages outgoing data, then reads incoming messages from the command stack as they arrive.

/* SSK 1.x — Remote Terminal (receive on a subaddress) */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_RT, 0, 0, 0);
 
/* RT address: hardwired or software-set */
naibrd_1553_RtSetAddressSource(devnum, NAI_1553_RT_ADDR_SRC_SOFTWARE);
naibrd_1553_RtSetAddress(devnum, RT_ADDR);
 
/* Create + legalize a receive data block on a subaddress */
naibrd_1553_RtDataBlockCreate(devnum, DBLK, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
naibrd_1553_RtDataBlockMapToSubaddress(devnum, DBLK, SUBADDR, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
naibrd_1553_RtStart(devnum);
 
/* Service incoming messages from the command stack as they arrive */
naibrd_1553_RtMessageGetFromStackRaw(devnum, buffer, MAX_MSG_SIZE, NAI_1553_RT_STACK_ACTIVE);
naibrd_1553_RtMessageDecodeRaw(devnum, buffer, &decoded);
 
naibrd_1553_RtStop(devnum);
naibrd_1553_Free(devnum);
/* SSK 2.x — Remote Terminal (receive on a subaddress) */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Init(devnum, NAIBRD_1553_ACCESS_CARD, NAIBRD_1553_MODE_RT, 0, 0, 0);
 
/* RT address: hardwired or software-set */
naibrd_1553_RtSetAddrSrc(devnum, NAIBRD_1553_RT_ADDR_SRC_SOFTWARE);
naibrd_1553_RtSetAddr(devnum, RT_ADDR);
 
/* Create + legalize a receive data block on a subaddress */
naibrd_1553_RtDataBlkCreate(devnum, DBLK, NAIBRD_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
naibrd_1553_RtDataBlkMapToSA(devnum, DBLK, SUBADDR, NAIBRD_1553_RT_MESSAGE_TYPE_RX, 0, 1);
naibrd_1553_RtStart(devnum);
 
/* Service incoming messages from the command stack as they arrive */
naibrd_1553_RtMsgGetFromStackRaw(devnum, buffer, NAIBRD_1553_MAX_MESSAGE_SIZE_RT, NAIBRD_1553_RT_STACK_ACTIVE);
naibrd_1553_RtMsgDecodeRaw(devnum, buffer, &decoded);
 
naibrd_1553_RtStop(devnum);
naibrd_1553_Free(devnum);

Try it — Bus Monitor

A monitor listens to every message on the bus and decodes them off the monitor stack. Optionally filter out RT/subaddress combinations you don’t care about.

/* SSK 1.x — Bus Monitor */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_MT, 0, 0, 0);
 
/* Optionally filter (e.g. ignore RT 7 SA 3): */
naibrd_1553_MtMessageMonitoringDisable(devnum, 7, NAI_1553_MT_FILTER_ALL, 1 << 3);
 
naibrd_1553_MtStart(devnum);
 
/* Pull messages off the monitor stack as they accumulate */
naibrd_1553_MtMessageGetFromStackRaw(devnum, buffer, NAI_1553_MAX_MESSAGE_SIZE_MT, NAI_1553_MT_STACK_ACTIVE);
naibrd_1553_MtMessageDecodeRaw(devnum, buffer, &decoded);
 
naibrd_1553_MtStop(devnum);
naibrd_1553_Free(devnum);
/* SSK 2.x — Bus Monitor */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Init(devnum, NAIBRD_1553_ACCESS_CARD, NAIBRD_1553_MODE_MT, 0, 0, 0);
 
/* Optionally filter (e.g. ignore RT 7 SA 3): */
naibrd_1553_MtMsgMonitoringDisable(devnum, 7, NAIBRD_1553_MT_FILTER_ALL, 1 << 3);
 
naibrd_1553_MtStart(devnum);
 
/* Pull messages off the monitor stack as they accumulate */
naibrd_1553_MtMsgGetFromStackRaw(devnum, buffer, NAIBRD_1553_MAX_MESSAGE_SIZE_MT, NAIBRD_1553_MT_STACK_ACTIVE);
naibrd_1553_MtMsgDecodeRaw(devnum, buffer, &decoded);
 
naibrd_1553_MtStop(devnum);
naibrd_1553_Free(devnum);

Try it — 1760 RT with EEPROM auto-init

On an FTJ/FTK, configure the channel as an RT, then unlock the EEPROM and copy the running configuration into it so the channel comes up already responding next power cycle.

/* SSK 1.x — 1760 RT + EEPROM copy */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_RT, 0, 0, 0);
 
/* Address comes from the hardwired pins on FTJ/FTK */
naibrd_1553_RtGetAddress(devnum, &rtAddr);
 
/* Configure the RT (legalize subaddress + stage initial data) */
naibrd_1553_RtDataBlockCreate(devnum, DBLK, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
naibrd_1553_RtDataBlockMapToSubaddress(devnum, DBLK, SUBADDR, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
naibrd_1553_RtDataBlockWrite(devnum, DBLK, initialData, WORDCOUNT, 0);
naibrd_1553_RtStart(devnum);
 
/* Snapshot the running config into EEPROM for the next power-up */
bool_t ready = FALSE;
naibrd_1760_SetEEPROMUnlock(devnum);
naibrd_1760_SetEECOPY(devnum, TRUE);
while (!ready) { naibrd_1760_GetDeviceReady(devnum, &ready); /* poll */ }
naibrd_1760_SetEECOPY(devnum, FALSE);
 
naibrd_1553_Free(devnum);
/* SSK 2.x — 1760 RT + EEPROM copy */
naibrd_1553_Open(cardIndex, module, channel, devnum);
naibrd_1553_Init(devnum, NAIBRD_1553_ACCESS_CARD, NAIBRD_1553_MODE_RT, 0, 0, 0);
 
/* Address comes from the hardwired pins on FTJ/FTK */
naibrd_1553_RtGetAddr(devnum, &rtAddr);
 
/* Configure the RT (legalize subaddress + stage initial data) */
naibrd_1553_RtDataBlkCreate(devnum, DBLK, NAIBRD_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
naibrd_1553_RtDataBlkMapToSA(devnum, DBLK, SUBADDR, NAIBRD_1553_RT_MESSAGE_TYPE_RX, 0, 1);
naibrd_1553_RtDataBlkWrite(devnum, DBLK, initialData, WORDCOUNT, 0);
naibrd_1553_RtStart(devnum);
 
/* Snapshot the running config into EEPROM for the next power-up */
bool_t ready = FALSE;
naibrd_1760_SetEEPROMUnlock(devnum);
naibrd_1760_SetEECOPY(devnum, TRUE);
while (!ready) { naibrd_1760_GetDeviceReady(devnum, &ready); /* poll */ }
naibrd_1760_SetEECOPY(devnum, FALSE);
 
naibrd_1553_Free(devnum);

Building and running the SSK samples. The snippets above are condensed for orientation. For full, buildable programs see the “Exercise it:” sample-app links under each role in Features — and Using NAI SSK 2.x Sample Applications · Using NAI SSK 1.x Sample Applications for build/run instructions across platforms.

Hardware capabilities and status monitoring

This section covers what the hardware provides and what you can monitor — for how to drive each role (and the messaging features that go with it: scheduling, async, retry, FIFO mode, mode codes), see Features and Try it above.

1553 hardware (FTA–FTF): Assisted Mode — an onboard ARM processor moves messages between the 1553 core and the host via command/response FIFOs, cutting host CPU load — plus 16K words/channel and the high-throughput Message FIFO mode used from the functions above.

MIL-STD-1760 hardware (FTJ/FTK): these are what make a 1760 store interface, layered on the 1553 core.

  • EEPROM auto-initialization as RT — the store powers up already configured as an RT (legalized subaddresses and pre-set data restored from EEPROM), responding within ~150 ms of power-on as MIL-STD-1760 requires, with no host setup. Program it via the 1760 store operation block above.
  • Power-on response timing — 1760 sets strict response deadlines after platform power is applied, and because module power settles before the core does, meeting them is a system-level concern; see the FTJ-FTK Manual for the timing budget.
  • Dedicated Holt-6130 transceiver for 1760’s tighter signal tolerances.
  • Hardwired RT address + parity — 5 address lines + parity per channel, latched on boot/reset (an RTxLOCK factory option blocks software address programming).
  • Interlock continuity path plus the other 1760 safety discretes, handled per the aircraft’s requirements.
  • 64K words of memory per channel (vs 16K on FTA–FTF).

Statuses you can monitor programmatically (both groups):

StatusWhat it tells youWhere
Block statusPer-message completion and error flags for a BC messageblockStatus in the decoded message struct (naibrd_1553_BcMsgGetByIdDecoded)
RT status wordThe responding RT’s MIL-STD-1553 status word (message error, busy, service request, etc.)status1 / status2 in the decoded struct
Channel statusReal-time/latched per-channel status with interrupt enablesChannel Status registers (Dynamic, Latched, Interrupt Enable, Set Edge/Level)
BIT statusPer-channel built-in-test resultBIT status register
Time tagPer-message timing for analysis/synchronizationtimeTag in the decoded struct
Message/RX availabilityMessages waiting (RT command stack depth, or Message FIFO count/threshold)RT command stack; Message FIFO Count register

ESP2’s status panel shows 1553 status interactively if you’d rather watch it in a GUI first.

Common pitfalls

  • Bus not terminated (or terminated wrong). A 1553 bus needs a terminator equal to the cable impedance (±2%, ~78 Ω) at both ends of the main bus. Missing or wrong termination causes reflections and message errors. Don’t add terminators at each stub.
  • Wrong coupling or over-long stub. Direct-coupled terminals (FTD/E/F) must be within 1 ft of the bus; transformer-coupled (FTA/B/C, FTJ/FTK) up to 20 ft. Exceeding the stub length for your coupling degrades signal integrity.
  • BC_DISABLE / M1760 not driven, so the channel won’t be BC. On a bench, enable the software override; in production, wire those pins and disable the override.
  • No response from the RT. The target RT may not be on the bus, may have the wrong address, or you sent on the wrong bus (A vs B). Verify the RT address, that the RT is active, and try the other bus.
  • RT not legalized / wrong subaddress. An RT only answers subaddresses you’ve legalized (Tx/Rx/Broadcast). If expected messages are ignored, check the legalization and the subaddress.
  • Incomplete BC frame hierarchy. naibrd_1553_BcStart needs a complete chain — major frame → minor frame → opcode → created message (with its data block). Build the whole hierarchy before starting.
  • (1760) Power-on timing is a system-level budget. Meeting 1760’s power-on response deadlines depends on your board’s power settling, not just the module — verify it at the system level (see the FTJ-FTK Manual).
  • (1760) RT address parity / not latched. FTJ/FTK latch the hardwired RT address (with odd parity) on boot/reset — a wrong parity or changing the lines after boot won’t take effect until reset.
  • (1760) Expecting auto-response without programming the EEPROM. A store only auto-initializes as a configured RT on power-up if you’ve programmed the EEPROM first; otherwise it comes up unconfigured.
  • Two Bus Controllers on one bus. Only one BC may run a 1553 bus at a time — a second active BC causes contention. Use RT or monitor mode for the other terminals.