import ctypes class UDP1553Header(ctypes.Structure): """ Represents the proprietary UDP header wrapping the MIL-STD-1553 frames. Based on the provided reference implementation. """ _pack_ = 1 _fields_ = [ ("marker1553", ctypes.c_uint16), ("vmajor", ctypes.c_uint8), ("vminor", ctypes.c_uint8), ("otype", ctypes.c_uint16), ("ta", ctypes.c_uint8), ("flags", ctypes.c_uint8), ("fcounter", ctypes.c_uint32), ("mcounter", ctypes.c_uint32), ("scounter", ctypes.c_uint32), ("mmiss", ctypes.c_uint32), ("smiss", ctypes.c_uint32), ("ltt", ctypes.c_uint32), ("errors", ctypes.c_uint32), ("bc_reserved", ctypes.c_uint32 * 2), ("rt_reserved", ctypes.c_uint32 * 2), ("spare", ctypes.c_uint32 * 3) ] # Constants identifying the packet structure MARKER_1553 = 0x1553 MARKER_END_1553 = 0x5315 OTYPE_BC = 0x4342 OTYPE_RT = 0x5452 # Error codes ERR_UNSUPPORTED_VERSION = 1 ERR_INVALID_SOURCE = 2 ERR_INVALID_LEN = 3 ERR_MISSED_MSG_MARKER = 4 def __init__(self, **kwargs): super().__init__(**kwargs) if "marker1553" not in kwargs: self.marker1553 = self.MARKER_1553 if "otype" not in kwargs: self.otype = self.OTYPE_BC class CommandWordStruct(ctypes.Structure): """ Bit-field representation of a 1553 Command Word. """ _pack_ = 1 _fields_ = [ ("word_count", ctypes.c_uint16, 5), # Bit 0-4: Word Count / Mode Code ("subaddress", ctypes.c_uint16, 5), # Bit 5-9: Subaddress ("tr_bit", ctypes.c_uint16, 1), # Bit 10: Transmit/Receive (1=Tx) ("remote_terminal", ctypes.c_uint16, 5)# Bit 11-15: Remote Terminal Address ] class CommandWordUnion(ctypes.Union): """ Union to access Command Word as raw integer or bit-fields. """ _pack_ = 1 _fields_ = [ ("raw", ctypes.c_uint16), ("struct", CommandWordStruct) ] def __init__(self, rt_addr=0, sub_addr=0, word_count=0, transmit=False): super().__init__() self.struct.remote_terminal = rt_addr self.struct.subaddress = sub_addr # According to 1553B, word count 0 usually means 32 words, # but logic here depends on specific implementation. # We store the value 0-31 directly. self.struct.word_count = word_count & 0x1F self.struct.tr_bit = 1 if transmit else 0 class UDP1553MessageHeader(ctypes.Structure): """ Header for a single 1553 Message inside the UDP packet payload. Followed immediately by the raw data words (not included in this struct). """ _pack_ = 1 _fields_ = [ ("marker", ctypes.c_uint16), ("command_word", CommandWordUnion), ("status_word", ctypes.c_uint16), ("error_code", ctypes.c_uint16) ] MARKER_BEGIN = 0x3C3C MARKER_END = 0x3E3E def __init__(self, command_word_union=None): super().__init__() self.marker = self.MARKER_BEGIN if command_word_union: self.command_word = command_word_union self.error_code = 0