168 lines
6.9 KiB
Python
168 lines
6.9 KiB
Python
from ..message_base import MessageBase
|
|
from ..constants import (
|
|
Subaddress, BullsEyeSelect, WaypointType, WaypointQualifier,
|
|
InterceptMode, LineStyle, SymbolState, Identity
|
|
)
|
|
from ..fields import BitField, EnumField, ScaledField, ASCIIField
|
|
|
|
class MsgA3(MessageBase):
|
|
"""
|
|
Message A3: Graphic Settings
|
|
|
|
ID: A3
|
|
Direction: BC -> RT (Receive)
|
|
Subaddress: 03
|
|
Rate: 6.25 Hz
|
|
Document Ref: 7.1.3
|
|
"""
|
|
SUBADDRESS = Subaddress.RX_GRAPHIC
|
|
IS_TRANSMIT = False
|
|
RATE_HZ = 6.25
|
|
|
|
# --- Word 01: Graphic Order (Ref 7.1.3.1) ---
|
|
# Graphic Symbols Enable Flags (1=Display)
|
|
show_waypoint_1 = BitField(word_index=0, start_bit=0, width=1)
|
|
show_waypoint_2 = BitField(word_index=0, start_bit=1, width=1)
|
|
show_waypoint_3 = BitField(word_index=0, start_bit=2, width=1)
|
|
show_intercept_fd = BitField(word_index=0, start_bit=3, width=1)
|
|
show_break_away_cue = BitField(word_index=0, start_bit=4, width=1)
|
|
show_intercept_zones = BitField(word_index=0, start_bit=5, width=1)
|
|
show_ttg_cursor = BitField(word_index=0, start_bit=6, width=1)
|
|
show_asec_circle = BitField(word_index=0, start_bit=7, width=1)
|
|
show_attack_steering = BitField(word_index=0, start_bit=8, width=1)
|
|
|
|
# Bull's Eye Selection
|
|
bullseye_select = EnumField(word_index=0, start_bit=9, width=2, enum_cls=BullsEyeSelect)
|
|
|
|
# Bits 11-15 Spare
|
|
|
|
# --- Word 02: Time-to-Go to Cursor (Ref 7.1.3.2) ---
|
|
# LSB = 1 sec
|
|
ttg_cursor = ScaledField(word_index=1, start_bit=0, width=16, lsb_value=1.0)
|
|
|
|
# --- Helper function for 25-bit Semicircles (Lat/Lon) ---
|
|
def _get_25bit_semicircle(self, word_idx_msw, word_idx_lsw):
|
|
"""
|
|
Combines MSW (16 bit) and LSW (9 bit) to form a 25-bit 2's complement
|
|
Semicircle value. LSB = 5.96046e-8.
|
|
"""
|
|
msw = self._data[word_idx_msw]
|
|
# LSW uses only bits 0-8 (9 bits)
|
|
lsw = (self._data[word_idx_lsw] >> 7) & 0x1FF
|
|
|
|
# Combine: MSW is top 16 bits, LSW is bottom 9 bits
|
|
raw_25 = (msw << 9) | lsw
|
|
|
|
# Handle 2's complement for 25 bits
|
|
if raw_25 & (1 << 24): # Sign bit check
|
|
raw_25 -= (1 << 25)
|
|
|
|
# Scale (1.0 full scale / 2^24) approx 5.96046e-8
|
|
return float(raw_25 * 5.9604644775e-8)
|
|
|
|
# --- Waypoint 1 Data (Ref 7.1.3.3 - 7.1.3.4) ---
|
|
# Raw accessors for internal use if needed, but properties are preferred
|
|
_wp1_lat_msw = BitField(word_index=2, start_bit=0, width=16)
|
|
_wp1_lat_lsw = BitField(word_index=3, start_bit=0, width=9) # Bits 0-8
|
|
|
|
@property
|
|
def wp1_latitude(self):
|
|
return self._get_25bit_semicircle(2, 3)
|
|
|
|
wp1_type = EnumField(word_index=3, start_bit=9, width=1, enum_cls=WaypointType)
|
|
wp1_qualifier_valid = BitField(word_index=3, start_bit=10, width=1)
|
|
wp1_qualifier_val = EnumField(word_index=3, start_bit=11, width=2, enum_cls=WaypointQualifier)
|
|
|
|
# WP1 Longitude
|
|
@property
|
|
def wp1_longitude(self):
|
|
return self._get_25bit_semicircle(4, 5)
|
|
|
|
wp1_code = BitField(word_index=5, start_bit=9, width=7) # 0-99
|
|
|
|
# --- Waypoint 2 Data (Ref 7.1.3.5 - 7.1.3.6) ---
|
|
@property
|
|
def wp2_latitude(self):
|
|
return self._get_25bit_semicircle(6, 7)
|
|
|
|
wp2_type = EnumField(word_index=7, start_bit=9, width=1, enum_cls=WaypointType)
|
|
wp2_qualifier_valid = BitField(word_index=7, start_bit=10, width=1)
|
|
wp2_qualifier_val = EnumField(word_index=7, start_bit=11, width=2, enum_cls=WaypointQualifier)
|
|
|
|
@property
|
|
def wp2_longitude(self):
|
|
return self._get_25bit_semicircle(8, 9)
|
|
|
|
wp2_code = BitField(word_index=9, start_bit=9, width=7)
|
|
|
|
# --- Waypoint 3 Data (Ref 7.1.3.7 - 7.1.3.8) ---
|
|
@property
|
|
def wp3_latitude(self):
|
|
return self._get_25bit_semicircle(10, 11)
|
|
|
|
wp3_type = EnumField(word_index=11, start_bit=9, width=1, enum_cls=WaypointType)
|
|
wp3_qualifier_valid = BitField(word_index=11, start_bit=10, width=1)
|
|
wp3_qualifier_val = EnumField(word_index=11, start_bit=11, width=2, enum_cls=WaypointQualifier)
|
|
|
|
@property
|
|
def wp3_longitude(self):
|
|
return self._get_25bit_semicircle(12, 13)
|
|
|
|
wp3_code = BitField(word_index=13, start_bit=9, width=7)
|
|
|
|
# --- Intercept Flight Director (Ref 7.1.3.9 - 7.1.3.10) ---
|
|
ifd_x = BitField(word_index=14, start_bit=0, width=9) # Pixels
|
|
ifd_mode = EnumField(word_index=14, start_bit=10, width=1, enum_cls=InterceptMode)
|
|
ifd_style = EnumField(word_index=14, start_bit=11, width=1, enum_cls=LineStyle)
|
|
|
|
ifd_y = BitField(word_index=15, start_bit=0, width=9) # Pixels
|
|
|
|
# --- Intercept Zones (Ref 7.1.3.11 - 7.1.3.14) ---
|
|
int_zone_rmin_y = BitField(word_index=16, start_bit=0, width=9)
|
|
int_zone_rmax_y = BitField(word_index=17, start_bit=0, width=9)
|
|
no_escape_rmax_y = BitField(word_index=18, start_bit=0, width=9)
|
|
int_zone_target_tip_y = BitField(word_index=19, start_bit=0, width=9)
|
|
|
|
# --- ASEC (Ref 7.1.3.15) ---
|
|
asec_radius = BitField(word_index=20, start_bit=0, width=9)
|
|
asec_blink = EnumField(word_index=20, start_bit=9, width=1, enum_cls=SymbolState)
|
|
|
|
# --- Attack Steering Cue (Ref 7.1.3.16 - 7.1.3.17) ---
|
|
asc_x = BitField(word_index=21, start_bit=0, width=9)
|
|
asc_blink = EnumField(word_index=21, start_bit=10, width=1, enum_cls=SymbolState)
|
|
asc_y = BitField(word_index=22, start_bit=0, width=9)
|
|
|
|
# --- Tracked Target Info (Ref 7.1.3.18) ---
|
|
hpt_in_int_zone = BitField(word_index=23, start_bit=0, width=1)
|
|
hpt_datalink_corr = BitField(word_index=23, start_bit=1, width=1)
|
|
hpt_identity = EnumField(word_index=23, start_bit=2, width=1, enum_cls=Identity)
|
|
|
|
spt_in_int_zone = BitField(word_index=23, start_bit=3, width=1)
|
|
spt_datalink_corr = BitField(word_index=23, start_bit=4, width=1)
|
|
spt_identity = EnumField(word_index=23, start_bit=5, width=1, enum_cls=Identity)
|
|
|
|
# TWS Targets in Zone (Bits 6-13)
|
|
tws_tgt_1_in_zone = BitField(word_index=23, start_bit=6, width=1)
|
|
tws_tgt_2_in_zone = BitField(word_index=23, start_bit=7, width=1)
|
|
# ... bits 8-13 follow same logic for targets 3-8
|
|
|
|
# --- Call Signs (Ref 7.1.3.19 - 7.1.3.20) ---
|
|
hpt_callsign_ab = ASCIIField(word_index=24) # Chars 1 & 2
|
|
hpt_callsign_cd = ASCIIField(word_index=25) # Chars 3 & 4
|
|
|
|
spt_callsign_ab = ASCIIField(word_index=26)
|
|
spt_callsign_cd = ASCIIField(word_index=27)
|
|
|
|
# --- Track IDs (Ref 7.1.3.21 - 7.1.3.24) ---
|
|
# These are 8-bit IDs. We use BitField manually.
|
|
tws_id_01 = BitField(word_index=28, start_bit=0, width=8)
|
|
tws_id_02 = BitField(word_index=28, start_bit=8, width=8)
|
|
|
|
tws_id_03 = BitField(word_index=29, start_bit=0, width=8)
|
|
tws_id_04 = BitField(word_index=29, start_bit=8, width=8)
|
|
|
|
tws_id_05 = BitField(word_index=30, start_bit=0, width=8)
|
|
tws_id_06 = BitField(word_index=30, start_bit=8, width=8)
|
|
|
|
tws_id_07 = BitField(word_index=31, start_bit=0, width=8)
|
|
tws_id_08 = BitField(word_index=31, start_bit=8, width=8) |