API

typedef struct temu_Mil1553BusIface {
  void (*connect)(void *Bus, int Subaddr, temu_Mil1553DevIfaceRef Device);
  void (*disconnect)(void *Bus, int Subaddr);
  void (*reportStats)(void *Bus);
  void (*send)(void *Bus, void *Sender, temu_Mil1553Msg *Msg);

  // Controls whether events should be issued at send calls
  void (*enableSendEvents)(void *Bus);
  void (*disableSendEvents)(void *Bus);
  void (*setBusController)(void *Bus, temu_Mil1553DevIfaceRef Device);
} temu_Mil1553BusIface;
typedef struct temu_Mil1553DevIface {
  void (*connected)(void *Device, temu_Mil1553BusIfaceRef Bus, int SubAddr);
  void (*disconnected)(void *Device, temu_Mil1553BusIfaceRef Bus, int SubAddr);
  void (*receive)(void *Device, temu_Mil1553Msg *Msg);
} temu_Mil1553DevIface;

Writing Clients

Bus Controllers and Remote Terminals

Bus controllers and remote terminals can be implemented using the Mil1553BusIface interface. This interface is defined in "temu-c/Bus/MilStd1553.h".

The interface consist of the connected, disconnected and receive functions. These are all mandatory and they are called whenever a virtual cable is connected and disconnected, or when a 1553 bus message is received.

A remote terminal needs to know about the bus it is connected to so it can use the send function in the Mil1553BusIface interface.

Do not call the bus send function from the device receive function, doing so will result in undefined behaviour. If a response is to be issued due to handling of a receive, ensure that an event is posted on the model’s event queue source.

The TEMU 1553 API follows the standard fairly well and subdivides 1553 transactions in phases which are command, data, status and mode command phases. To send a receive command, the bus controller will first send a message of the type teMT_Cmd, followed by a teMT_Data message. The remote terminal is then expected to respond with a teMT_Stat message. The remote terminal and bus controller model is responsible for issuing the different messages with delays. Delays can be computed using the temu_mil1553TransferTime() function.

Messages should be sent in whole when they are supposed to arrive. This means that the bus controller model can immediately raise any needed interrupts when a message is complete.

The TEMU default 1553 bus model will print error messages if a remote terminal does not follow the 1553 protocol phases properly (e.g. sending a status response to a broadcast message).
void
receive(void *Device, temu_Mil1553Msg *Msg)
{
  MyRT *RT = (MyRT*)Device;
  //...
  // Start sending response
  temu_eventPostNanos(RT->Super.TimeSource, RT->TransferCompleteEvent,
                      temu_mil1553TransferTime(1), // One word for status message
                      teSE_Cpu);
}

void
transferComplete(temu_Event *Ev)
{
   MyRT *RT = (MyRT*)Ev->Obj;

   uint16_t Stat = computeStatWord(RT);
   temu_Mil1553Msg Msg = temu_mil1553CreateStatMsg(&Stat);

   RT->Bus.Iface->send(RT->Bus.Obj, RT, &Msg); // Send the message
}

Bus Monitors

The 1553 bus interface does not support the implementation of bus monitors directly at this moment. The reason for this is that, the message notification interface already allows the system to inspect all the bus traffic executed. The notification interface can also be used to modify traffic in situ (e.g. to flip the error flags in the message object). Terma appreciates that there may be need for some users to support modelling of bus monitors, please contact Terma if this is needed.

Capture Device

TEMU is bundled with a MILBUS capture device that enables capturing of the bus traffic. There are three supported options for message capture:

  • Logging command words issued to the TEMU log with partial decoding

  • CSV output with command words and partial decodes of them

  • PCAPNG file with all data transferred. File can be loaded in Wireshark if needed.

To create a logging capture device, create the bus capture instance using:

For logging: object-create class=MilStd1553BusCapturer name=milbus-cap0 \ args=fmt:log,bus:milbus0

For CSV output (into milbus0.csv): object-create class=MilStd1553BusCapturer name=milbus-cap0 \ args=fmt:csv,bus:milbus0

For PCAPNG output (into milbus0.pcapng): object-create class=MilStd1553BusCapturer name=milbus-cap0 \ args=fmt:pcapng,bus:milbus0

Do not forget to set the time source for the capture device: connect-timesource obj=milbus-cap0 ts=cpu0

While the logging and CSV modes should be clear enough, there are some notes to be providede regarding the PCAPNG format.

Firstly, the capture model captures logical units in the protocol, that is, command words are captured by themselves, as is status messages and data messages.

Secondly, the capture model use the flags in the frame block to mark where the data came from. That is, it flags unicast, and broadcast messages as such, and it also flags the direction as outbound for frames emitted by the BC (e.g. command words, mode codes, data sent to RTs etc) and inbound for data sent from RTs.

Thirdly, LINKTYPE_USER0 is used for the device type (there is no standardised milbus link type), this linktype is not supported directly by Wireshark, and a dissector needs to be implemented to make frames more human readable.

Due to these caveats, interpreting the 1553 protocol in Wireshark is a bit tricky, but in general, we can say that command sequences starts with outbound frames, which are followed by inbound frames. A dissector (or human viewing without a dissector) needs to be clever about decoding these frames and take into account the previous frames sent, it is likely also necessary in case of failed transfers to take into account such flags as well as buscontrollers tend to retry message transfers if they fail.