From 5981895494ec077c85f8114bc6c97db73e99ae9f Mon Sep 17 00:00:00 2001
From: BBK <22713769+BlueberryKing@users.noreply.github.com>
Date: Mon, 21 Nov 2022 20:00:54 +0100
Subject: [PATCH] feat(rmp): RMP navigation tuning #7241 (@494aa9f)
---
.github/CHANGELOG.md | 1 +
docs/a320-simvars.md | 49 +++
.../A32NX/AirlinerCommon.xml | 339 +++++++++++++++++-
.../model/A320_NEO_INTERIOR.xml | 284 +++++++--------
flybywire-aircraft-a320-neo/en-US.locPak | 10 +
flybywire-aircraft-a320-neo/fr-FR.locPak | 10 +
.../CDU/A320_Neo_CDU_NavRadioPage.js | 167 ++++++---
.../CDU/A320_Neo_CDU_SelectedNavaids.js | 13 +-
.../FMC/A32NX_FMCMainDisplay.js | 77 +++-
src/behavior/src/A32NX_Interior_RMP.xml | 39 +-
src/fmgc/src/radionav/NavRadioManager.ts | 37 +-
.../src/ND/elements/RadioNavInfo.tsx | 13 +-
src/instruments/src/ND/pages/RoseMode.tsx | 8 +-
src/instruments/src/PFD/HeadingIndicator.tsx | 3 +-
.../src/PFD/LandingSystemIndicator.tsx | 9 +-
src/instruments/src/PFD/instrument.tsx | 1 +
.../src/PFD/shared/PFDSimvarPublisher.tsx | 3 +
.../src/RMP/Components/BaseRadioPanels.tsx | 97 ++++-
.../src/RMP/Components/NavRadioPanel.tsx | 163 +++++++++
.../src/RMP/Components/RadioPanelDisplay.tsx | 28 +-
.../src/RMP/Components/StandbyCourse.tsx | 44 +++
.../src/RMP/Components/StandbyFrequency.tsx | 82 ++++-
.../src/RMP/Components/VhfRadioPanel.tsx | 12 +-
23 files changed, 1173 insertions(+), 316 deletions(-)
create mode 100644 src/instruments/src/RMP/Components/NavRadioPanel.tsx
create mode 100644 src/instruments/src/RMP/Components/StandbyCourse.tsx
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 4a803bc1a35..6261447351b 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -100,6 +100,7 @@
1. [HYD] Implemented Electro Hydrostatic actuators - @Crocket63 (crocket)
1. [FAC] Move Speedscale computation to FAC - @lukecologne (luke)
1. [EFB] Added pause at T/D function - @2hwk (2Cas#1022)
+1. [RMP] RMPs navigation backup - Julian Sebline (Julian Sebline#8476 on Discord)
## 0.8.0
diff --git a/docs/a320-simvars.md b/docs/a320-simvars.md
index d58fea92000..fdada096d32 100644
--- a/docs/a320-simvars.md
+++ b/docs/a320-simvars.md
@@ -371,6 +371,10 @@
- Number
- The current mode of the right radio management panel.
+- A32NX_RMP_{L,R}_NAV_BUTTON_SELECTED
+ - Bool
+ - Whether the NAV push button on the corresponding RMP is pushed or not.
+
- A32NX_RMP_L_VHF2_STANDBY
- Hz
- The VHF 2 standby frequency for the left RMP.
@@ -387,6 +391,42 @@
- Hz
- The VHF 3 standby frequency for the right RMP.
+- A32NX_RMP_{L,R}_SAVED_ACTIVE_FREQUENCY_VOR
+ - Hz
+ - The VOR active frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_ACTIVE_FREQUENCY_ILS
+ - Hz
+ - The ILS active frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_ACTIVE_FREQUENCY_ADF
+ - Hz
+ - The ADF active frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_STANDBY_FREQUENCY_VOR
+ - Hz
+ - The VOR standby frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_STANDBY_FREQUENCY_ILS
+ - Hz
+ - The ILS standby frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_STANDBY_FREQUENCY_ADF
+ - Hz
+ - The ADF standby frequency that is saved for display for the left/right RMP.
+
+- A32NX_RMP_{L,R}_SAVED_COURSE_VOR
+ - Number
+ - The VOR course tuned via the left/right RMP
+
+- A32NX_RMP_{L,R}_SAVED_COURSE_ILS
+ - Number
+ - The ILS course tuned via the left/right RMP
+
+- A32NX_RMP_ILS_TUNED
+ - Bool
+ - If the ILS is tuned via the RMP
+
- A32NX_TO_CONFIG_FLAPS_ENTERED
- Bool
- True if the pilot has entered a FLAPS value in the PERF TAKE OFF takeoff
@@ -1011,6 +1051,15 @@
GOAROUND | 6
DONE | 7
+- A32NX_FMGC_RADIONAV_TUNING_MODE
+ - Enum
+ - Hold the FMGCs current tuning mode
+ Value | Meaning
+ --- | ---
+ 0 | AUTO
+ 1 | MANUAL
+ 2 | REMOTE VIA RMPs
+
- A32NX_FLAPS_HANDLE_INDEX
- Number
- Indicates the physical flaps handle position
diff --git a/flybywire-aircraft-a320-neo/ModelBehaviorDefs/A32NX/AirlinerCommon.xml b/flybywire-aircraft-a320-neo/ModelBehaviorDefs/A32NX/AirlinerCommon.xml
index cf366cabd1c..2dc26f20905 100644
--- a/flybywire-aircraft-a320-neo/ModelBehaviorDefs/A32NX/AirlinerCommon.xml
+++ b/flybywire-aircraft-a320-neo/ModelBehaviorDefs/A32NX/AirlinerCommon.xml
@@ -278,8 +278,11 @@
1
0.04
0.01
+ 0.02
AIRLINER
- 1
+ (L:A32NX_ELEC_DC_ESS_BUS_IS_POWERED, Bool)
+ (L:A32NX_ELEC_DC_ESS_BUS_IS_POWERED, Bool)
+ (L:A32NX_ELEC_DC_ESS_BUS_IS_POWERED, Bool)
@@ -318,6 +321,7 @@
#PREFIX#_AudioReceiver_Push_mic_call_03#SUFFIX_ID#
#PREFIX#_AudioReceiver_Push_mic_call_03_SEQ1#SUFFIX_ID#
#PREFIX#_AudioReceiver_Push_mic_call_03_SEQ2#SUFFIX_ID#
+ #PREFIX#_AudioReceiver_Knob_MKR_LED#SUFFIX_ID#
False
@@ -396,6 +400,267 @@
TT:COCKPIT.TOOLTIPS.TRANSMITTER_VHF_R_AUDIO_TOGGLE
TT:COCKPIT.TOOLTIPS.TRANSMITTER_SELECT_VHF_R
+
+
+ BUTTON
+ #NODE_ID_RECEIVER_VOICE#
+ #ANIM_NAME_PUSH_RECEIVER_VOICE#
+ #NODE_ID_BUTTON_VOICE_SEQ1#
+ #NODE_ID_BUTTON_VOICE_SEQ2#
+
+ (L:XMLVAR_NAV_#SIDE#_VOICE_Switch_Down) ! (>L:XMLVAR_NAV_#SIDE#_VOICE_Switch_Down)
+ (L:XMLVAR_NAV_L_VOICE_Switch_Down) (L:XMLVAR_NAV_R_VOICE_Switch_Down) or (>L:XMLVAR_NAV_VOICE_Switch_Down)
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 0 == if{
+ (L:XMLVAR_NAV_L_VOR1_Switch_Down) (L:XMLVAR_NAV_R_VOR1_Switch_Down) or if{
+ 1 (>K:RADIO_VOR1_IDENT_ENABLE)
+ 1 (>K:RADIO_DME1_IDENT_ENABLE)
+ }
+ (L:XMLVAR_NAV_L_VOR2_Switch_Down) (L:XMLVAR_NAV_R_VOR2_Switch_Down) or if{
+ 1 (>K:RADIO_VOR2_IDENT_ENABLE)
+ 1 (>K:RADIO_DME2_IDENT_ENABLE)
+ }
+
+ (L:XMLVAR_NAV_L_ADF1_Switch_Down) (L:XMLVAR_NAV_R_ADF1_Switch_Down) or if{
+ 1 (>K:RADIO_ADF_IDENT_ENABLE)
+ }
+ (L:XMLVAR_NAV_L_ADF2_Switch_Down) (L:XMLVAR_NAV_R_ADF2_Switch_Down) or if{
+ 1 (>K:RADIO_ADF2_IDENT_ENABLE)
+ }
+ }
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 1 == if{
+ 1 (>K:RADIO_VOR1_IDENT_DISABLE)
+ 1 (>K:RADIO_VOR2_IDENT_DISABLE)
+ 1 (>K:RADIO_ADF_IDENT_DISABLE)
+ 1 (>K:RADIO_ADF2_IDENT_DISABLE)
+
+ 1 (>K:RADIO_DME1_IDENT_DISABLE)
+ 1 (>K:RADIO_DME2_IDENT_DISABLE)
+ }
+
+ fcubutton
+ 0.1
+ fcubutton
+ 0.5
+ (L:XMLVAR_NAV_#SIDE#_VOICE_Switch_Down)
+ %((L:XMLVAR_NAV_#SIDE#_VOICE_Switch_Down))%{if}TT:COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_OFF%{else}TT:COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_ON%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_VOR1#
+ #NODE_ID_LIGHT_RECEIVER_VOR1#
+ #ANIM_NAME_KNOB_RECEIVER_VOR1#
+ #ANIM_NAME_PUSH_RECEIVER_VOR1#
+ VOR1
+
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 0 == if{
+ (A:NAV SOUND:1, Bool) 1 == (L:XMLVAR_NAV_L_VOR1_Switch_Down) 0 == (L:XMLVAR_NAV_R_VOR1_Switch_Down) 0 == and and if{
+ 1 (>K:RADIO_VOR1_IDENT_TOGGLE)
+ 1 (>K:RADIO_DME1_IDENT_SET)
+ }
+
+ (A:NAV SOUND:1, Bool) 0 == (L:XMLVAR_NAV_L_VOR1_Switch_Down) 1 == (L:XMLVAR_NAV_R_VOR1_Switch_Down) 1 == or and if{
+ 1 (>K:RADIO_VOR1_IDENT_TOGGLE)
+ 1 (>K:RADIO_DME1_IDENT_SET)
+ }
+ }
+
+
+
+ (L:XMLVAR_NAV_#SIDE#_VOR1_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_VOR1_Volume)
+ (L:XMLVAR_NAV_#SIDE#_VOR1_Volume) (A:NAV VOLUME:1, percent over 100) > if{
+ 1 (>K:NAV1_VOLUME_INC)
+ }
+
+
+ (L:XMLVAR_NAV_#SIDE#_VOR1_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_VOR1_Volume)
+ (L:XMLVAR_NAV_L_VOR1_Volume) (L:XMLVAR_NAV_R_VOR1_Volume) max (A:NAV VOLUME:1, percent over 100) < if{
+ 1 (>K:NAV1_VOLUME_DEC)
+ }
+
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_VOR1_VOLUME_DEC
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_VOR1_VOLUME_INC
+ %((L:XMLVAR_NAV_#SIDE#_VOR1_Switch_Down))%{if}TT:INPUT.KEY_RADIO_VOR1_IDENT_DISABLE_DESC%{else}TT:INPUT.KEY_RADIO_VOR1_IDENT_ENABLE_DESC%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_VOR2#
+ #NODE_ID_LIGHT_RECEIVER_VOR2#
+ #ANIM_NAME_KNOB_RECEIVER_VOR2#
+ #ANIM_NAME_PUSH_RECEIVER_VOR2#
+ VOR2
+
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 0 == if{
+ (A:NAV SOUND:2, Bool) 1 == (L:XMLVAR_NAV_L_VOR2_Switch_Down) 0 == (L:XMLVAR_NAV_R_VOR2_Switch_Down) 0 == and and if{
+ 1 (>K:RADIO_VOR2_IDENT_TOGGLE)
+ 1 (>K:RADIO_DME2_IDENT_SET)
+ }
+
+ (A:NAV SOUND:2, Bool) 0 == (L:XMLVAR_NAV_L_VOR2_Switch_Down) 1 == (L:XMLVAR_NAV_R_VOR2_Switch_Down) 1 == or and if{
+ 1 (>K:RADIO_VOR2_IDENT_TOGGLE)
+ 1 (>K:RADIO_DME2_IDENT_SET)
+ }
+ }
+
+
+
+ (L:XMLVAR_NAV_#SIDE#_VOR2_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_VOR2_Volume)
+ (L:XMLVAR_NAV_#SIDE#_VOR2_Volume) (A:NAV VOLUME:2, percent over 100) > if{
+ 1 (>K:NAV2_VOLUME_INC)
+ }
+
+
+ (L:XMLVAR_NAV_#SIDE#_VOR2_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_VOR2_Volume)
+ (L:XMLVAR_NAV_L_VOR2_Volume) (L:XMLVAR_NAV_R_VOR2_Volume) max (A:NAV VOLUME:2, percent over 100) < if{
+ 1 (>K:NAV2_VOLUME_DEC)
+ }
+
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_VOR2_VOLUME_DEC
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_VOR2_VOLUME_INC
+ %((L:XMLVAR_NAV_#SIDE#_VOR2_Switch_Down))%{if}TT:INPUT.KEY_RADIO_VOR2_IDENT_DISABLE_DESC%{else}TT:INPUT.KEY_RADIO_VOR2_IDENT_ENABLE_DESC%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_MKR#
+ #NODE_ID_LIGHT_RECEIVER_MKR#
+ #ANIM_NAME_KNOB_RECEIVER_MKR#
+ #ANIM_NAME_PUSH_RECEIVER_MKR#
+ #NODE_ID_LED_RECEIVER_MKR#
+ MKR
+
+ (A:MARKER SOUND, Bool) 1 == (L:XMLVAR_NAV_L_MKR_Switch_Down) 0 == (L:XMLVAR_NAV_R_MKR_Switch_Down) 0 == and and if{
+ 1 (>K:MARKER_SOUND_TOGGLE)
+ }
+
+ (A:MARKER SOUND, Bool) 0 == (L:XMLVAR_NAV_L_MKR_Switch_Down) 1 == (L:XMLVAR_NAV_R_MKR_Switch_Down) 1 == or and if{
+ 1 (>K:MARKER_SOUND_TOGGLE)
+ }
+
+
+ (L:XMLVAR_NAV_#SIDE#_MKR_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_MKR_Volume)
+ (L:XMLVAR_NAV_#SIDE#_MKR_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_MKR_Volume)
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_DECREASE
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_INCREASE
+ %((L:XMLVAR_NAV_#SIDE#_MKR_Switch_Down))%{if}TT:COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_DISABLE%{else}TT:COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_ENABLE%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_ILS#
+ #NODE_ID_LIGHT_RECEIVER_ILS#
+ #ANIM_NAME_KNOB_RECEIVER_ILS#
+ #ANIM_NAME_PUSH_RECEIVER_ILS#
+ #NODE_ID_LED_RECEIVER_ILS#
+ ILS
+
+
+
+ (L:XMLVAR_NAV_#SIDE#_ILS_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_ILS_Volume)
+ (L:XMLVAR_NAV_#SIDE#_ILS_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_ILS_Volume)
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_DECREASE
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_INCREASE
+ %((L:XMLVAR_NAV_#SIDE#_ILS_Switch_Down))%{if}TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_DISABLE%{else}TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_ENABLE%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_MLS#
+ #NODE_ID_LIGHT_RECEIVER_MLS#
+ #ANIM_NAME_KNOB_RECEIVER_MLS#
+ #ANIM_NAME_PUSH_RECEIVER_MLS#
+ #NODE_ID_LED_RECEIVER_MLS#
+ MLS
+
+
+
+ (L:XMLVAR_NAV_#SIDE#_MLS_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_MLS_Volume)
+ (L:XMLVAR_NAV_#SIDE#_MLS_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_MLS_Volume)
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_DECREASE
+ TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_INCREASE
+ %((L:XMLVAR_NAV_#SIDE#_MLS_Switch_Down))%{if}TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_DISABLE%{else}TT:COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_ENABLE%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_ADF1#
+ #NODE_ID_LIGHT_RECEIVER_ADF1#
+ #ANIM_NAME_KNOB_RECEIVER_ADF1#
+ #ANIM_NAME_PUSH_RECEIVER_ADF1#
+ #NODE_ID_LED_RECEIVER_ADF1#
+ ADF1
+
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 0 == if{
+ (A:ADF SOUND, Bool) 1 == (L:XMLVAR_NAV_L_ADF1_Switch_Down) 0 == (L:XMLVAR_NAV_R_ADF1_Switch_Down) 0 == and and if{
+ 1 (>K:RADIO_ADF_IDENT_DISABLE)
+ }
+
+ (A:ADF SOUND, Bool) 0 == (L:XMLVAR_NAV_L_ADF1_Switch_Down) 1 == (L:XMLVAR_NAV_R_ADF1_Switch_Down) 1 == or and if{
+ 1 (>K:RADIO_ADF_IDENT_ENABLE)
+ }
+ }
+
+
+
+ (L:XMLVAR_NAV_#SIDE#_ADF1_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_ADF1_Volume)
+ (L:XMLVAR_NAV_#SIDE#_ADF1_Volume) (A:ADF VOLUME:1, percent over 100) > if{
+ 1 (>K:ADF_VOLUME_INC)
+ }
+
+
+ (L:XMLVAR_NAV_#SIDE#_ADF1_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_ADF1_Volume)
+ (L:XMLVAR_NAV_L_ADF1_Volume) (L:XMLVAR_NAV_R_ADF1_Volume) max (A:ADF VOLUME:1, percent over 100) < if{
+ 1 (>K:ADF_VOLUME_DEC)
+ }
+
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_ADF1_VOLUME_DEC
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_ADF1_VOLUME_INC
+ %((L:XMLVAR_NAV_#SIDE#_ADF1_Switch_Down))%{if}TT:INPUT.KEY_RADIO_ADF_IDENT_DISABLE_DESC%{else}TT:INPUT.KEY_RADIO_ADF_IDENT_ENABLE_DESC%{end}
+
+
+
+ KNOB
+ FBW_AIRLINER_Audio_NAV_Volume_Knob_Template
+ #NODE_ID_RECEIVER_ADF2#
+ #NODE_ID_LIGHT_RECEIVER_ADF2#
+ #ANIM_NAME_KNOB_RECEIVER_ADF2#
+ #ANIM_NAME_PUSH_RECEIVER_ADF2#
+ #NODE_ID_LED_RECEIVER_ADF2#
+ ADF2
+
+
+ (L:XMLVAR_NAV_VOICE_Switch_Down) 0 == if{
+ (A:ADF SOUND:2, Bool) 1 == (L:XMLVAR_NAV_L_ADF2_Switch_Down) 0 == (L:XMLVAR_NAV_R_ADF2_Switch_Down) 0 == and and if{
+ 1 (>K:RADIO_ADF2_IDENT_TOGGLE)
+ }
+
+ (A:ADF SOUND:2, Bool) 0 == (L:XMLVAR_NAV_L_ADF2_Switch_Down) 1 == (L:XMLVAR_NAV_R_ADF2_Switch_Down) 1 == or and if{
+ 1 (>K:RADIO_ADF2_IDENT_TOGGLE)
+ }
+ }
+
+
+ (L:XMLVAR_NAV_#SIDE#_ADF2_Volume) #VOLUME_INCREMENT_NAV# + 1 min (>L:XMLVAR_NAV_#SIDE#_ADF2_Volume)
+ (L:XMLVAR_NAV_#SIDE#_ADF2_Volume) #VOLUME_INCREMENT_NAV# - 0 max (>L:XMLVAR_NAV_#SIDE#_ADF2_Volume)
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_ADF2_VOLUME_DEC
+ TT:COCKPIT.TOOLTIPS.TRANSMITTER_ADF2_VOLUME_INC
+ %((L:XMLVAR_NAV_#SIDE#_ADF2_Switch_Down))%{if}TT:INPUT.KEY_RADIO_ADF2_IDENT_DISABLE_DESC%{else}TT:INPUT.KEY_RADIO_ADF2_IDENT_ENABLE_DESC%{end}
+
@@ -417,7 +682,7 @@
1 (L:XMLVAR_COM_#ID#_#FREQ_ID#_Switch_Down) == (L:A32NX_OVHD_INTLT_ANN) 0 == or if{
3.0 #EMISSIVE_DIM# *
} els{
- 0
+ 0.1 #EMISSIVE_DIM# *
}
}
@@ -539,6 +804,76 @@
+
+
+
+
+
+
+ ASOBO_GT_Knob_Finite_Switch
+ #ANIM_CODE_SWITCH#
+ 1
+ (L:A32NX_OVHD_INTLT_ANN, number) 2 == if{ 0.1 } els{ 1 }
+
+
+
+ #AUDIO_KNOB_POWERED# ! if{
+ 0
+ } els{
+ (L:XMLVAR_NAV_#SIDE#_#INSTRUMENT#_Switch_Down) 1 == (L:A32NX_OVHD_INTLT_ANN) 0 == or if{
+ 3.0 #EMISSIVE_DIM# *
+ } els{
+ 0.1 #EMISSIVE_DIM# *
+ }
+ }
+
+
+
+
+
+ #ANIM_NAME_KNOB#
+ 1
+ 0
+ 1
+ TurnLeft
+ TurnRight
+ Hand
+ #TOOLTIP_LEFT#
+ #TOOLTIP_RIGHT#
+ #TOOLTIP_HAND#
+ True
+ False
+ False
+ 0.002
+ (L:XMLVAR_NAV_#SIDE#_#INSTRUMENT#_Volume) 100 *
+ #INC_VOLUME#
+ #DEC_VOLUME#
+ (L:XMLVAR_NAV_#SIDE#_#INSTRUMENT#_Switch_Down) 100 *
+ #ANIM_NAME_SWITCH#
+
+ (L:XMLVAR_NAV_#SIDE#_#INSTRUMENT#_Switch_Down) ! (>L:XMLVAR_NAV_#SIDE#_#INSTRUMENT#_Switch_Down)
+
+ #ONCLICK#
+
+
+ mcdubuttons
+ 0.1
+ mcdubuttons
+ 0.5
+ 36
+
+
+
+
+
+ #TRANSMIT_EMISSIVE_CODE#
+
+
+
+
+
+
+
diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
index 0623b80eabb..42136fa1123 100644
--- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
+++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
@@ -4138,13 +4138,19 @@
-
+
0 (>L:XMLVAR_COM_PANEL1_Transmit_Channel)
+ 4 (>L:XMLVAR_COM_PANEL2_Transmit_Channel)
+
0 (>K:PILOT_TRANSMITTER_SET)
+ 4 (>K:COPILOT_TRANSMITTER_SET)
1 (>L:XMLVAR_COM_1_VHF_L_Switch_Down)
1 (>L:XMLVAR_COM_1_VHF_C_Switch_Down)
+ 1 (>L:XMLVAR_COM_2_VHF_L_Switch_Down)
+ 1 (>L:XMLVAR_COM_2_VHF_C_Switch_Down)
1 (>K:COM1_RECEIVE_SELECT)
1 (>K:COM2_RECEIVE_SELECT)
@@ -4152,8 +4158,8 @@
0.8 (>L:XMLVAR_COM_1_Volume_VHF_L)
0.4 (>L:XMLVAR_COM_1_Volume_VHF_C)
- 0 (>L:XMLVAR_COM_1_Volume_VHF_R)
- 0 (>K:COM3_VOLUME_SET)
+ 0.8 (>L:XMLVAR_COM_2_Volume_VHF_L)
+ 0.4 (>L:XMLVAR_COM_2_Volume_VHF_C)
1
@@ -4180,6 +4186,47 @@
PUSH_AUDIOL_VHF3
PUSH_AUDIOL_CALL3
PUSH_AUDIOL_CALL3
+
+ PUSH_AUDIOL_VOICE
+ PUSH_AUDIOL_VOICE
+ PUSH_AUDIOL_VOICE_SEQ1
+ PUSH_AUDIOL_VOICE_SEQ2
+
+ KNOB_AUDIOL_MKR
+ PUSH_AUDIOL_MKR_EMIS
+ KNOB_AUDIOL_MKR
+ PUSH_AUDIOL_MKR
+
+ KNOB_AUDIOL_VOR1
+ PUSH_AUDIOL_VOR1_EMIS
+ KNOB_AUDIOL_VOR1
+ PUSH_AUDIOL_VOR1
+
+ KNOB_AUDIOL_VOR2
+ PUSH_AUDIOL_VOR2_EMIS
+ KNOB_AUDIOL_VOR2
+ PUSH_AUDIOL_VOR2
+
+ KNOB_AUDIOL_ILS
+ PUSH_AUDIOL_ILS_EMIS
+ KNOB_AUDIOL_ILS
+ PUSH_AUDIOL_ILS
+
+ KNOB_AUDIOL_MLS
+ PUSH_AUDIOL_MLS_EMIS
+ KNOB_AUDIOL_MLS
+ PUSH_AUDIOL_MLS
+
+ KNOB_AUDIOL_ADF1
+ PUSH_AUDIOL_ADF1_EMIS
+ KNOB_AUDIOL_ADF1
+ PUSH_AUDIOL_ADF1
+
+ KNOB_AUDIOL_ADF2
+ PUSH_AUDIOL_ADF2_EMIS
+ KNOB_AUDIOL_ADF2
+ PUSH_AUDIOL_ADF2
+
PUSH_AUDIOL_CALL3_SEQ1
PUSH_AUDIOL_CALL3_SEQ2
@@ -4197,11 +4244,6 @@
0
0
-
- PUSH_AUDIOL_VOICE
- 0
- 0
-
PUSH_AUDIOL_PA
0
@@ -4229,46 +4271,18 @@
-
- PUSH_AUDIOL_VOR1_EMIS
- 0
-
-
- PUSH_AUDIOL_VOR2_EMIS
- 0
-
-
- PUSH_AUDIOL_MKR_EMIS
- 0
-
-
- PUSH_AUDIOL_ILS_EMIS
- 0
-
PUSH_AUDIOL_HF1_EMIS
0
-
- PUSH_AUDIOL_MLS_EMIS
- 0
-
PUSH_AUDIOL_HF2_EMIS
0
-
- PUSH_AUDIOL_ADF1_EMIS
- 0
-
PUSH_AUDIOL_INT_EMIS
0
-
- PUSH_AUDIOL_ADF2_EMIS
- 0
-
PUSH_AUDIOL_CAB_EMIS
0
@@ -4331,6 +4345,46 @@
PUSH_AUDIOR_CALL3
PUSH_AUDIOR_CALL3_SEQ1
PUSH_AUDIOR_CALL3_SEQ2
+
+ PUSH_AUDIOR_VOICE
+ PUSH_AUDIOR_VOICE
+ PUSH_AUDIOR_VOICE_SEQ1
+ PUSH_AUDIOR_VOICE_SEQ2
+
+ KNOB_AUDIOR_MKR
+ PUSH_AUDIOR_MKR_EMIS
+ KNOB_AUDIOR_MKR
+ PUSH_AUDIOR_MKR
+
+ KNOB_AUDIOR_VOR1
+ PUSH_AUDIOR_VOR1_EMIS
+ KNOB_AUDIOR_VOR1
+ PUSH_AUDIOR_VOR1
+
+ KNOB_AUDIOR_VOR2
+ PUSH_AUDIOR_VOR2_EMIS
+ KNOB_AUDIOR_VOR2
+ PUSH_AUDIOR_VOR2
+
+ KNOB_AUDIOR_ILS
+ PUSH_AUDIOR_ILS_EMIS
+ KNOB_AUDIOR_ILS
+ PUSH_AUDIOR_ILS
+
+ KNOB_AUDIOR_MLS
+ PUSH_AUDIOR_MLS_EMIS
+ KNOB_AUDIOR_MLS
+ PUSH_AUDIOR_MLS
+
+ KNOB_AUDIOR_ADF1
+ PUSH_AUDIOR_ADF1_EMIS
+ KNOB_AUDIOR_ADF1
+ PUSH_AUDIOR_ADF1
+
+ KNOB_AUDIOR_ADF2
+ PUSH_AUDIOR_ADF2_EMIS
+ KNOB_AUDIOR_ADF2
+ PUSH_AUDIOR_ADF2
@@ -4346,11 +4400,6 @@
0
0
-
- PUSH_AUDIOR_VOICE
- 0
- 0
-
PUSH_AUDIOR_PA
0
@@ -4378,46 +4427,18 @@
-
- PUSH_AUDIOR_VOR1_EMIS
- 0
-
-
- PUSH_AUDIOR_VOR2_EMIS
- 0
-
-
- PUSH_AUDIOR_MKR_EMIS
- 0
-
-
- PUSH_AUDIOR_ILS_EMIS
- 0
-
PUSH_AUDIOR_HF1_EMIS
0
-
- PUSH_AUDIOR_MLS_EMIS
- 0
-
PUSH_AUDIOR_HF2_EMIS
0
-
- PUSH_AUDIOR_ADF1_EMIS
- 0
-
PUSH_AUDIOR_INT_EMIS
0
-
- PUSH_AUDIOR_ADF2_EMIS
- 0
-
PUSH_AUDIOR_CAB_EMIS
0
@@ -4428,6 +4449,41 @@
+
+
+
+ (A:MARKER SOUND, Bool) 1 == {
+ (>K:MARKER_SOUND_TOGGLE)
+ }
+
+ 0 (>K:NAV1_VOLUME_SET)
+ 0 (>K:NAV2_VOLUME_SET)
+ 0 (>K:NAV3_VOLUME_SET)
+ 0 (>K:NAV4_VOLUME_SET)
+
+ 0 (>K:ADF_VOLUME_SET)
+ 0 (>K:ADF2_VOLUME_SET)
+
+ 113000000 (>L:A32NX_RMP_L_SAVED_ACTIVE_FREQUENCY_VOR)
+ 113000000 (>L:A32NX_RMP_L_SAVED_STANDBY_FREQUENCY_VOR)
+ 113000000 (>L:A32NX_RMP_R_SAVED_ACTIVE_FREQUENCY_VOR)
+ 113000000 (>L:A32NX_RMP_R_SAVED_STANDBY_FREQUENCY_VOR)
+
+ 108900000 (>L:A32NX_RMP_L_SAVED_ACTIVE_FREQUENCY_ILS)
+ 108900000 (>L:A32NX_RMP_L_SAVED_STANDBY_FREQUENCY_ILS)
+ 108900000 (>L:A32NX_RMP_R_SAVED_ACTIVE_FREQUENCY_ILS)
+ 108900000 (>L:A32NX_RMP_R_SAVED_STANDBY_FREQUENCY_ILS)
+
+ 433000 (>L:A32NX_RMP_L_SAVED_ACTIVE_FREQUENCY_ADF)
+ 433000 (>L:A32NX_RMP_L_SAVED_STANDBY_FREQUENCY_ADF)
+ 433000 (>L:A32NX_RMP_R_SAVED_ACTIVE_FREQUENCY_ADF)
+ 433000 (>L:A32NX_RMP_R_SAVED_STANDBY_FREQUENCY_ADF)
+
+ 22 (>L:A32NX_RMP_L_SAVED_COURSE_VOR)
+ 202 (>L:A32NX_RMP_L_SAVED_COURSE_ILS)
+ 22 (>L:A32NX_RMP_R_SAVED_COURSE_VOR)
+ 202 (>L:A32NX_RMP_R_SAVED_COURSE_ILS)
+
@@ -4899,51 +4955,6 @@
PUSH_AUDIOL_RESET
-
- PUSH_AUDIOL_VOICE
-
-
- PUSH_AUDIOL_ADF2
-
-
- KNOB_AUDIOL_ADF2
-
-
- PUSH_AUDIOL_ADF1
-
-
- KNOB_AUDIOL_ADF1
-
-
- PUSH_AUDIOL_MLS
-
-
- KNOB_AUDIOL_MLS
-
-
- PUSH_AUDIOL_ILS
-
-
- KNOB_AUDIOL_ILS
-
-
- PUSH_AUDIOL_MKR
-
-
- KNOB_AUDIOL_MKR
-
-
- PUSH_AUDIOL_VOR1
-
-
- KNOB_AUDIOL_VOR1
-
-
- PUSH_AUDIOL_VOR2
-
-
- KNOB_AUDIOL_VOR2
-
PUSH_AUDIOL_PA
@@ -4977,51 +4988,6 @@
PUSH_AUDIOR_RESET
-
- PUSH_AUDIOR_VOICE
-
-
- PUSH_AUDIOR_ADF2
-
-
- KNOB_AUDIOR_ADF2
-
-
- PUSH_AUDIOR_ADF1
-
-
- KNOB_AUDIOR_ADF1
-
-
- PUSH_AUDIOR_MLS
-
-
- KNOB_AUDIOR_MLS
-
-
- PUSH_AUDIOR_ILS
-
-
- KNOB_AUDIOR_ILS
-
-
- PUSH_AUDIOR_MKR
-
-
- KNOB_AUDIOR_MKR
-
-
- PUSH_AUDIOR_VOR1
-
-
- KNOB_AUDIOR_VOR1
-
-
- PUSH_AUDIOR_VOR2
-
-
- KNOB_AUDIOR_VOR2
-
PUSH_AUDIOR_PA
diff --git a/flybywire-aircraft-a320-neo/en-US.locPak b/flybywire-aircraft-a320-neo/en-US.locPak
index 8931ba81b59..40b6072bad8 100755
--- a/flybywire-aircraft-a320-neo/en-US.locPak
+++ b/flybywire-aircraft-a320-neo/en-US.locPak
@@ -14,6 +14,16 @@
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_L_PFD_INCREASE": "Increase left PFD brightness",
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_R_PFD_DECREASE": "Decrease right PFD brightness",
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_R_PFD_INCREASE": "Increase right PFD brightness",
+ "COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_OFF": "Allow morse ident",
+ "COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_ON": "Inhibit morse ident",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_INCREASE": "Increase the volume of the ident of the Markers beacons",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_DECREASE": "Decrease the volume of the ident of the Markers beacons",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_ENABLE": "Turn on the ident of the Markers beacons",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_DISABLE": "Turn off the ident of the Markers beacons",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_INCREASE": "Increase the volume of the ident of the ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_DECREASE": "Decrease the volume of the ident of the ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_ENABLE": "Turn on the ident of the ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_DISABLE": "Turn off the ident of the ILS",
"COCKPIT.TOOLTIPS.LIGHTS_NOSMOKE_AUTO": "Set \"no smoke\" prompt light to AUTO",
"COCKPIT.TOOLTIPS.APU_AVAILABLE": "APU available",
"A32NX.LOADING.TIPS.A320NEO_001": "The FlyByWire A32NX is a collaboration between hundreds of individual contributors.",
diff --git a/flybywire-aircraft-a320-neo/fr-FR.locPak b/flybywire-aircraft-a320-neo/fr-FR.locPak
index 1f66db91ab2..4dbeeea7b44 100644
--- a/flybywire-aircraft-a320-neo/fr-FR.locPak
+++ b/flybywire-aircraft-a320-neo/fr-FR.locPak
@@ -15,6 +15,16 @@
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_L_PFD_INCREASE": "Augmenter la luminosité du PFD gauche",
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_R_PFD_DECREASE": "Réduire la luminosité du PDF droit",
"COCKPIT.TOOLTIPS.LIGHTING_KNOB_R_PFD_INCREASE": "Augmenter la luminosité du PDF droit",
+ "COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_OFF": "Autoriser l'identification morse",
+ "COCKPIT.TOOLTIPS.NAV_PUSHBUTTON_VOICE_ON": "Inhiber l'identification morse",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_INCREASE": "Augmenter le volume de l'identification des balises Markers",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_VOLUME_DECREASE": "Diminuer le volume de l'identification des balises Marker",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_ENABLE": "Activer l'identification des balises Markers",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_MARKERS_IDENT_DISABLE": "Désactiver l'identification des balises Markers",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_INCREASE": "Augmenter le volume de l'identification de l'ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_VOLUME_DECREASE": "Diminuer le volume de l'identification de l'ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_ENABLE": "Activer l'identification de l'ILS",
+ "COCKPIT.TOOLTIPS.NAV_KNOB_ILS_IDENT_DISABLE": "Désactiver l'identification de l'ILS",
"COCKPIT.TOOLTIPS.LIGHTS_NOSMOKE_AUTO": "Mettre le témoin d'interdiction de fumer en mode AUTO",
"A32NX.LOADING.TIPS.A320NEO_001": "Le FlyByWire A32NX est le fruit d'une collaboration entre des centaines de contributeurs individuels.",
"A32NX.LOADING.TIPS.A320NEO_002": "Le saviez-vous ? L'A320 peut atterrir par vent de travers jusqu'à 38 nœuds et avec un vent arrière jusqu'à 15 nœuds !",
diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_NavRadioPage.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_NavRadioPage.js
index 5598fd24ac9..14e36aaf61b 100644
--- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_NavRadioPage.js
+++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_NavRadioPage.js
@@ -9,11 +9,12 @@ class CDUNavRadioPage {
mcdu.returnPageCallback = () => {
CDUNavRadioPage.ShowPage(mcdu);
};
+
const radioOn = mcdu.isRadioNavActive();
let vor1FrequencyCell = "";
let vor1CourseCell = "";
let ilsFrequencyCell = "";
- let ilsCourseCell = "[ ]";
+ let ilsCourseCell = "";
let adf1FrequencyCell = "";
let adf1BfoOption = "";
let vor2FrequencyCell = "";
@@ -29,15 +30,24 @@ class CDUNavRadioPage {
}, mcdu.PageTimeout.Default);
if (!radioOn) {
- vor1FrequencyCell = "[\xa0]/[\xa0\xa0.\xa0]";
- const vor1Beacon = mcdu.radioNav.getVORBeacon(1);
- const vor1Ident = vor1Beacon && vor1Beacon.ident.length >= 2 && vor1Beacon.ident.length <= 3 ? vor1Beacon.ident : "";
- if (mcdu.vor1Frequency && !mcdu.vor1IdIsPilotEntered && mcdu.vor1FreqIsPilotEntered) {
- vor1FrequencyCell = "{small}" + vor1Ident.padStart(3, "\xa0") + "{end}" + "/" + mcdu.vor1Frequency.toFixed(2);
- } else if (mcdu.vor1Frequency && mcdu.vor1IdIsPilotEntered && !mcdu.vor1FreqIsPilotEntered) {
- vor1FrequencyCell = mcdu.vor1IdPilotValue.padStart(3, "\xa0") + "/" + "{small}" + mcdu.vor1Frequency.toFixed(2) + "{end}";
+ if (!mcdu.backupNavTuning) {
+ vor1FrequencyCell = "[\xa0]/[\xa0\xa0.\xa0]";
+ const vor1Beacon = mcdu.radioNav.getVORBeacon(1);
+ const vor1Ident = vor1Beacon && vor1Beacon.ident.length >= 2 && vor1Beacon.ident.length <= 3 ? vor1Beacon.ident : "";
+ if (mcdu.vor1Frequency && !mcdu.vor1IdIsPilotEntered && mcdu.vor1FreqIsPilotEntered) {
+ vor1FrequencyCell = "{small}" + vor1Ident.padStart(3, "\xa0") + "{end}" + "/" + mcdu.vor1Frequency.toFixed(2);
+ } else if (mcdu.vor1Frequency && mcdu.vor1IdIsPilotEntered && !mcdu.vor1FreqIsPilotEntered) {
+ vor1FrequencyCell = mcdu.vor1IdPilotValue.padStart(3, "\xa0") + "/" + "{small}" + mcdu.vor1Frequency.toFixed(2) + "{end}";
+ }
}
+
mcdu.onLeftInput[0] = (value, scratchpadCallback) => {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (value === FMCMainDisplay.clrValue) {
mcdu.vor1FreqIsPilotEntered = false;
@@ -97,11 +107,19 @@ class CDUNavRadioPage {
scratchpadCallback();
}
};
- vor1CourseCell = "[\xa0]";
- if (mcdu.vor1Course > 0) {
- vor1CourseCell = mcdu.vor1Course.toFixed(0).padStart(3, "0");
+ if (!mcdu.backupNavTuning) {
+ vor1CourseCell = "[\xa0]";
+ if (mcdu.vor1Course > 0) {
+ vor1CourseCell = mcdu.vor1Course.toFixed(0).padStart(3, "0");
+ }
}
mcdu.onLeftInput[1] = (value, scratchpadCallback) => {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (isFinite(numValue) && numValue > 0 && numValue <= 360) {
SimVar.SetSimVarValue("K:VOR1_SET", "number", numValue).then(() => {
@@ -118,26 +136,31 @@ class CDUNavRadioPage {
scratchpadCallback();
}
};
- ilsFrequencyCell = "[\xa0\xa0]/[\xa0\xa0.\xa0]";
- if (mcdu.ilsFrequency != 0) {
- if (mcdu._ilsFrequencyPilotEntered) {
- const ilsIdent = mcdu.radioNav.getILSBeacon(1);
- ilsFrequencyCell = `{small}${ilsIdent.ident.trim().padStart(4, "\xa0")}{end}/${mcdu.ilsFrequency.toFixed(2)}`;
- } else if (mcdu._ilsIdentPilotEntered) {
- ilsFrequencyCell = `${mcdu._ilsIdent.trim().padStart(4, "\xa0")}/{small}${mcdu.ilsFrequency.toFixed(2)}{end}`;
- } else if (mcdu.ilsAutoTuned) {
- ilsFrequencyCell = `{small}${mcdu.ilsAutoIdent.padStart(4, "\xa0")}/${mcdu.ilsFrequency.toFixed(2)}{end}`;
- }
- const lsCourse = SimVar.GetSimVarValue('L:A32NX_FM_LS_COURSE', 'number');
- if (lsCourse >= 0) {
- ilsCourseCell = `{${mcdu.ilsCourse !== undefined ? 'big' : 'small'}}F${lsCourse.toFixed(0).padStart(3, "0")}{end}`;
- } else if (mcdu._ilsFrequencyPilotEntered) {
- ilsCourseCell = "{amber}____{end}";
+ if (!mcdu.backupNavTuning) {
+ ilsFrequencyCell = "[\xa0\xa0]/[\xa0\xa0.\xa0]";
+ if (mcdu.ilsFrequency != 0) {
+ if (mcdu._ilsFrequencyPilotEntered) {
+ const ilsIdent = mcdu.radioNav.getILSBeacon(1);
+ ilsFrequencyCell = `{small}${ilsIdent.ident.trim().padStart(4, "\xa0")}{end}/${mcdu.ilsFrequency.toFixed(2)}`;
+ } else if (mcdu._ilsIdentPilotEntered) {
+ ilsFrequencyCell = `${mcdu._ilsIdent.trim().padStart(4, "\xa0")}/{small}${mcdu.ilsFrequency.toFixed(2)}{end}`;
+ } else if (mcdu.ilsAutoTuned) {
+ ilsFrequencyCell = `{small}${mcdu.ilsAutoIdent.padStart(4, "\xa0")}/${mcdu.ilsFrequency.toFixed(2)}{end}`;
+ }
+
+ const lsCourse = SimVar.GetSimVarValue('L:A32NX_FM_LS_COURSE', 'number');
+ ilsCourseCell = "[\xa0]";
+ if (lsCourse >= 0) {
+ ilsCourseCell = `{${mcdu.ilsCourse !== undefined ? 'big' : 'small'}}F${lsCourse.toFixed(0).padStart(3, "0")}{end}`;
+ } else if (mcdu._ilsFrequencyPilotEntered) {
+ ilsCourseCell = "{amber}____{end}";
+ }
}
}
+
mcdu.onLeftInput[2] = (value, scratchpadCallback) => {
- mcdu.setIlsFrequency(value, (result) => {
+ mcdu.setIlsFrequency(value, mcdu.backupNavTuning, (result) => {
if (result) {
mcdu.requestCall(() => {
CDUNavRadioPage.ShowPage(mcdu);
@@ -148,7 +171,7 @@ class CDUNavRadioPage {
});
};
mcdu.onLeftInput[3] = (value, scratchpadCallback) => {
- mcdu.setLsCourse(value, (result) => {
+ mcdu.setLsCourse(value, mcdu.backupNavTuning, (result) => {
if (result) {
mcdu.requestCall(() => {
CDUNavRadioPage.ShowPage(mcdu);
@@ -158,16 +181,25 @@ class CDUNavRadioPage {
}
});
};
- adf1FrequencyCell = "[\xa0]/[\xa0\xa0\xa0.]";
- const adf1Ident = SimVar.GetSimVarValue(`ADF IDENT:1`, "string");
- if (mcdu.adf1Frequency != 0 && !mcdu.adf1IdIsPilotEntered && mcdu.adf1FreqIsPilotEntered) {
- adf1FrequencyCell = "{small}" + adf1Ident.padStart(3, "\xa0") + "{end}" + "/" + mcdu.adf1Frequency.toFixed(1);
- adf1BfoOption = " {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (!isFinite(numValue) && value.length >= 2 && value.length <= 3) {
mcdu.getOrSelectNDBsByIdent(value, (navaids) => {
@@ -218,15 +250,24 @@ class CDUNavRadioPage {
}
if (!radioOn) {
- vor2FrequencyCell = "[\xa0\xa0.\xa0]/[\xa0]";
- const vor2Beacon = mcdu.radioNav.getVORBeacon(2);
- const vor2Ident = vor2Beacon && vor2Beacon.ident.length >= 2 && vor2Beacon.ident.length <= 3 ? vor2Beacon.ident : "";
- if (mcdu.vor2Frequency != 0 && mcdu.vor2FreqIsPilotEntered && !mcdu.vor2IdIsPilotEntered) {
- vor2FrequencyCell = mcdu.vor2Frequency.toFixed(2) + "/" + "{small}" + vor2Ident.padEnd(3, "\xa0") + "{end}";
- } else if (mcdu.vor2Frequency != 0 && !mcdu.vor2FreqIsPilotEntered && mcdu.vor2IdIsPilotEntered) {
- vor2FrequencyCell = "{small}" + mcdu.vor2Frequency.toFixed(2) + "{end}" + "/" + mcdu.vor2IdPilotValue.padEnd(3, "\xa0");
+ if (!mcdu.backupNavTuning) {
+ vor2FrequencyCell = "[\xa0\xa0.\xa0]/[\xa0]";
+ const vor2Beacon = mcdu.radioNav.getVORBeacon(2);
+ const vor2Ident = vor2Beacon && vor2Beacon.ident.length >= 2 && vor2Beacon.ident.length <= 3 ? vor2Beacon.ident : "";
+ if (mcdu.vor2Frequency != 0 && mcdu.vor2FreqIsPilotEntered && !mcdu.vor2IdIsPilotEntered) {
+ vor2FrequencyCell = mcdu.vor2Frequency.toFixed(2) + "/" + "{small}" + vor2Ident.padEnd(3, "\xa0") + "{end}";
+ } else if (mcdu.vor2Frequency != 0 && !mcdu.vor2FreqIsPilotEntered && mcdu.vor2IdIsPilotEntered) {
+ vor2FrequencyCell = "{small}" + mcdu.vor2Frequency.toFixed(2) + "{end}" + "/" + mcdu.vor2IdPilotValue.padEnd(3, "\xa0");
+ }
}
+
mcdu.onRightInput[0] = (value, scratchpadCallback) => {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (value === FMCMainDisplay.clrValue) {
mcdu.vor2FreqIsPilotEntered = false;
@@ -286,11 +327,20 @@ class CDUNavRadioPage {
scratchpadCallback();
}
};
- vor2CourseCell = "[\xa0]";
- if (mcdu.vor2Course > 0) {
- vor2CourseCell = mcdu.vor2Course.toFixed(0).padStart(3, "0");
+
+ if (!mcdu.backupNavTuning) {
+ vor2CourseCell = "[\xa0]";
+ if (mcdu.vor2Course > 0) {
+ vor2CourseCell = mcdu.vor2Course.toFixed(0).padStart(3, "0");
+ }
}
mcdu.onRightInput[1] = (value, scratchpadCallback) => {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (isFinite(numValue) && numValue > 0 && numValue <= 360) {
SimVar.SetSimVarValue("K:VOR2_SET", "number", numValue).then(() => {
@@ -307,16 +357,25 @@ class CDUNavRadioPage {
scratchpadCallback();
}
};
- adf2FrequencyCell = "[\xa0\xa0\xa0.]/[\xa0]";
- const adf2Ident = SimVar.GetSimVarValue(`ADF IDENT:2`, "string");
- if (mcdu.adf2Frequency > 0 && mcdu.adf2FreqIsPilotEntered && !mcdu.adf2IdIsPilotEntered) {
- adf2FrequencyCell = mcdu.adf2Frequency.toFixed(1) + "/" + "{small}" + adf2Ident.padEnd(3, "\xa0") + "{end}";
- adf2BfoOption = "ADF2 BFO>";
- } else if (mcdu.adf2Frequency > 0 && !mcdu.adf2FreqIsPilotEntered && mcdu.adf2IdIsPilotEntered) {
- adf2FrequencyCell = "{small}" + mcdu.adf2Frequency.toFixed(1) + "{end}" + "/" + mcdu.adf2IdPilotValue.padEnd(3, "\xa0");
- adf2BfoOption = "ADF2 BFO>";
+
+ if (!mcdu.backupNavTuning) {
+ adf2FrequencyCell = "[\xa0\xa0\xa0.]/[\xa0]";
+ const adf2Ident = SimVar.GetSimVarValue(`ADF IDENT:2`, "string");
+ if (mcdu.adf2Frequency > 0 && mcdu.adf2FreqIsPilotEntered && !mcdu.adf2IdIsPilotEntered) {
+ adf2FrequencyCell = mcdu.adf2Frequency.toFixed(1) + "/" + "{small}" + adf2Ident.padEnd(3, "\xa0") + "{end}";
+ adf2BfoOption = "ADF2 BFO>";
+ } else if (mcdu.adf2Frequency > 0 && !mcdu.adf2FreqIsPilotEntered && mcdu.adf2IdIsPilotEntered) {
+ adf2FrequencyCell = "{small}" + mcdu.adf2Frequency.toFixed(1) + "{end}" + "/" + mcdu.adf2IdPilotValue.padEnd(3, "\xa0");
+ adf2BfoOption = "ADF2 BFO>";
+ }
}
mcdu.onRightInput[4] = (value, scratchpadCallback) => {
+ if (mcdu.backupNavTuning) {
+ mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
+ scratchpadCallback();
+ return false;
+ }
+
const numValue = parseFloat(value);
if (!isFinite(numValue) && value.length >= 2 && value.length <= 3) {
mcdu.adf2FreqIsPilotEntered = false;
diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_SelectedNavaids.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_SelectedNavaids.js
index 7d12ee1c3aa..1aaaa92038c 100644
--- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_SelectedNavaids.js
+++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_SelectedNavaids.js
@@ -3,9 +3,20 @@ class CDUSelectedNavaids {
mcdu.clearDisplay();
mcdu.page.Current = mcdu.page.SelectedNavaids;
+ let mode = "AUTO";
+ if (mcdu.backupNavTuning) {
+ mode = "RMP";
+ } else if (mcdu.vor1IdIsPilotEntered || mcdu.vor1FreqIsPilotEntered ||
+ mcdu.vor2IdIsPilotEntered || mcdu.vor2FreqIsPilotEntered ||
+ mcdu._ilsFrequencyPilotEntered || mcdu._ilsIdentPilotEntered ||
+ mcdu.adf1IdIsPilotEntered || mcdu.adf1FreqIsPilotEntered ||
+ mcdu.adf2IdIsPilotEntered || mcdu.adf2FreqIsPilotEntered) {
+ mode = "MAN";
+ }
+
mcdu.setTemplate([
["\xa0SELECTED NAVAIDS"],
- ["\xa0VOR/TAC", "DESELECT", "AUTO"],
+ ["\xa0VOR/TAC", "DESELECT", mode],
[``, `[\xa0\xa0\xa0]{small}*{end}[color]cyan`, ""],
[""],
[""],
diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js
index 6dc1012736b..002de5744db 100644
--- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js
+++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js
@@ -182,6 +182,8 @@ class FMCMainDisplay extends BaseAirliners {
this.efisSymbols = undefined;
this.groundTempAuto = undefined;
this.groundTempPilot = undefined;
+ this.backupNavTuning = false;
+ this.manualNavTuning = false;
/**
* Landing elevation in feet MSL.
* This is the destination runway threshold elevation, or airport elevation if runway is not selected.
@@ -571,6 +573,8 @@ class FMCMainDisplay extends BaseAirliners {
onUpdate(_deltaTime) {
super.onUpdate(_deltaTime);
+ this.navRadioManager.update(_deltaTime, this.manualNavTuning, this.backupNavTuning);
+
this.flightPlanManager.update(_deltaTime);
const flightPlanChanged = this.flightPlanManager.currentFlightPlanVersion !== this.lastFlightPlanVersion;
if (flightPlanChanged) {
@@ -1255,6 +1259,31 @@ class FMCMainDisplay extends BaseAirliners {
SimVar.SetSimVarValue("K:TOGGLE_GPS_DRIVES_NAV1", "Bool", 0);
}
}
+
+ this.backupNavTuning = SimVar.GetSimVarValue("L:A32NX_RMP_L_NAV_BUTTON_SELECTED", "Bool")
+ || SimVar.GetSimVarValue("L:A32NX_RMP_R_NAV_BUTTON_SELECTED", "Bool");
+
+ // Cannot be manual if RMP tuned. It erases everything
+ if (this.backupNavTuning && this.manualNavTuning) {
+ this.vor1IdIsPilotEntered = false;
+ this.vor1FreqIsPilotEntered = false;
+ this.vor2IdIsPilotEntered = false;
+ this.vor2FreqIsPilotEntered = false;
+ this._ilsFrequencyPilotEntered = false;
+ this._ilsIdentPilotEntered = false;
+ this.adf1IdIsPilotEntered = false;
+ this.adf1FreqIsPilotEntered = false;
+ this.adf2IdIsPilotEntered = false;
+ this.adf2FreqIsPilotEntered = false;
+
+ this.manualNavTuning = false;
+ } else {
+ this.manualNavTuning = this.vor1IdIsPilotEntered || this.vor1FreqIsPilotEntered ||
+ this.vor2IdIsPilotEntered || this.vor2FreqIsPilotEntered ||
+ this._ilsFrequencyPilotEntered || this._ilsIdentPilotEntered ||
+ this.adf1IdIsPilotEntered || this.adf1FreqIsPilotEntered ||
+ this.adf2IdIsPilotEntered || this.adf2FreqIsPilotEntered;
+ }
}
updateAutopilot() {
@@ -2364,6 +2393,13 @@ class FMCMainDisplay extends BaseAirliners {
}
async updateIls() {
+ if (this.backupNavTuning) {
+ if (this.ilsAutoTuned) {
+ this.clearAutotunedIls();
+ }
+ return;
+ }
+
await this.updateIlsCourse();
if (this.flightPhaseManager.phase > FmgcFlightPhases.TAKEOFF) {
@@ -2432,11 +2468,13 @@ class FMCMainDisplay extends BaseAirliners {
} else if (this.ilsFrequency > 0 && SimVar.GetSimVarValue('L:A32NX_RADIO_RECEIVER_LOC_IS_VALID', 'number') === 1) {
course = SimVar.GetSimVarValue('NAV LOCALIZER:3', 'degrees');
}
+ SimVar.SetSimVarValue('L:A32NX_RMP_ILS_TUNED', 'boolean', false);
+
return SimVar.SetSimVarValue('L:A32NX_FM_LS_COURSE', 'number', course);
}
isRunwayLsMismatched() {
- if (!this.ilsAutoTuned || this.flightPhaseManager.phase === FmgcFlightPhases.DONE) {
+ if (this.backupNavTuning || !this.ilsAutoTuned || this.flightPhaseManager.phase === FmgcFlightPhases.DONE) {
return false;
}
@@ -2444,7 +2482,7 @@ class FMCMainDisplay extends BaseAirliners {
}
isRunwayLsCourseMismatched() {
- if (!this.ilsAutoTuned || this.ilsCourse === undefined) {
+ if (this.backupNavTuning || !this.ilsAutoTuned || this.ilsCourse === undefined) {
return false;
}
@@ -3910,7 +3948,12 @@ class FMCMainDisplay extends BaseAirliners {
}
}
- setIlsFrequency(s, callback) {
+ setIlsFrequency(s, navpushbutton, callback) {
+ if (navpushbutton) {
+ this.setScratchpadMessage(NXSystemMessages.notAllowed);
+ return callback(false);
+ }
+
if (s === FMCMainDisplay.clrValue) {
if (!this._ilsIdentPilotEntered && !this._ilsFrequencyPilotEntered) {
this.setScratchpadMessage(NXSystemMessages.notAllowed);
@@ -3984,8 +4027,9 @@ class FMCMainDisplay extends BaseAirliners {
}
}
- setLsCourse(s, callback) {
- if (!this.ilsAutoTuned && !this._ilsFrequencyPilotEntered && !this._ilsIdentPilotEntered) {
+ setLsCourse(s, navpushbutton, callback) {
+ if ((!this.ilsAutoTuned && !this._ilsFrequencyPilotEntered && !this._ilsIdentPilotEntered) ||
+ navpushbutton) {
this.setScratchpadMessage(NXSystemMessages.notAllowed);
return callback(false);
}
@@ -4047,6 +4091,10 @@ class FMCMainDisplay extends BaseAirliners {
}
}
{
+ if (_boot) {
+ // Because by default, it's set to a frequency beyond operational range
+ this.radioNav.setILSStandbyFrequency(1, 108.9);
+ }
if (Math.abs(this.radioNav.getVORActiveFrequency(1) - this.vor1Frequency) > 0.005) {
this.radioNav.setVORActiveFrequency(1, this.vor1Frequency);
}
@@ -4067,18 +4115,13 @@ class FMCMainDisplay extends BaseAirliners {
}
}
{
- if (_boot) {
- this.adf1Frequency = this.radioNav.getADFActiveFrequency(1);
- this.adf2Frequency = this.radioNav.getADFActiveFrequency(2);
- } else {
- if (Math.abs(this.radioNav.getADFActiveFrequency(1) - this.adf1Frequency) > 0.005) {
- SimVar.SetSimVarValue("K:ADF_COMPLETE_SET", "Frequency ADF BCD32", Avionics.Utils.make_adf_bcd32(this.adf1Frequency * 1000)).then(() => {
- });
- }
- if (Math.abs(this.radioNav.getADFActiveFrequency(2) - this.adf2Frequency) > 0.005) {
- SimVar.SetSimVarValue("K:ADF2_COMPLETE_SET", "Frequency ADF BCD32", Avionics.Utils.make_adf_bcd32(this.adf2Frequency * 1000)).then(() => {
- });
- }
+ if (Math.abs(this.radioNav.getADFActiveFrequency(1) - this.adf1Frequency) > 0.005) {
+ SimVar.SetSimVarValue("K:ADF_COMPLETE_SET", "Frequency ADF BCD32", Avionics.Utils.make_adf_bcd32(this.adf1Frequency * 1000)).then(() => {
+ });
+ }
+ if (Math.abs(this.radioNav.getADFActiveFrequency(2) - this.adf2Frequency) > 0.005) {
+ SimVar.SetSimVarValue("K:ADF2_COMPLETE_SET", "Frequency ADF BCD32", Avionics.Utils.make_adf_bcd32(this.adf2Frequency * 1000)).then(() => {
+ });
}
}
{
diff --git a/src/behavior/src/A32NX_Interior_RMP.xml b/src/behavior/src/A32NX_Interior_RMP.xml
index 58fc50a96bc..67c1b7d33d4 100644
--- a/src/behavior/src/A32NX_Interior_RMP.xml
+++ b/src/behavior/src/A32NX_Interior_RMP.xml
@@ -118,6 +118,7 @@
FBW_RMP_MODE_BUTTON_AND_LED
1
HF1
+ 4
@@ -126,6 +127,7 @@
FBW_RMP_MODE_BUTTON_AND_LED
1
HF2
+ 5
@@ -134,6 +136,7 @@
FBW_RMP_MODE_BUTTON_AND_LED
1
AM
+ 11
@@ -149,11 +152,11 @@
alias annunciatorLight = (L:A32NX_OVHD_INTLT_ANN, number);
let emissiveDim = if annunciatorLight == 2 { 0.05 } else { 1 };
// @todo abnormal defined differently with NAV modes available.
- let rmpLeftAbnormal = selectedModeLeft != 1 or selectedModeRight == 1;
- let rmpRightAbnormal = selectedModeRight != 2 or selectedModeLeft == 2;
- let sideLeftCheck = id == 1;
- let sideRightCheck = id == 2;
- (if (toggleSwitch and ((rmpLeftAbnormal and sideLeftCheck) or (rmpRightAbnormal and sideRightCheck)) or (annunciatorLight == 0)) and indicatorsPowered {
+
+ let rmpLeftAbnormal = id == 1 and (selectedModeLeft == 2 or selectedModeLeft == 3 or selectedModeRight == 1);
+ let rmpRightAbnormal = id == 2 and (selectedModeRight == 1 or selectedModeRight == 3 or selectedModeLeft == 2);
+
+ (if (toggleSwitch and (rmpLeftAbnormal or rmpRightAbnormal) or (annunciatorLight == 0)) and indicatorsPowered {
1 * emissiveDim
} else {
0
@@ -175,11 +178,11 @@
alias annunciatorLight = (L:A32NX_OVHD_INTLT_ANN, number);
let emissiveDim = if annunciatorLight == 2 { 0.05 } else { 1 };
// @todo abnormal defined differently with NAV modes available.
- let rmpLeftAbnormal = selectedModeLeft != 1 or selectedModeRight == 1;
- let rmpRightAbnormal = selectedModeRight != 2 or selectedModeLeft == 2;
- let sideLeftCheck = id == 1;
- let sideRightCheck = id == 2;
- (if (toggleSwitch and ((rmpLeftAbnormal and sideLeftCheck) or (rmpRightAbnormal and sideRightCheck)) or (annunciatorLight == 0)) and indicatorsPowered {
+
+ let rmpLeftAbnormal = id == 1 and (selectedModeLeft == 2 or selectedModeLeft == 3 or selectedModeRight == 1);
+ let rmpRightAbnormal = id == 2 and (selectedModeRight == 1 or selectedModeRight == 3 or selectedModeLeft == 2);
+
+ (if (toggleSwitch and (rmpLeftAbnormal or rmpRightAbnormal) or (annunciatorLight == 0)) and indicatorsPowered {
1 * emissiveDim
} else {
0
@@ -216,15 +219,15 @@
BUTTON
FBW_RMP_MODE_BUTTON_AND_LED
- 1
NAV
+ 12
BUTTON
FBW_RMP_MODE_BUTTON_AND_LED
- 1
+ 6
VOR
@@ -232,24 +235,24 @@
BUTTON
FBW_RMP_MODE_BUTTON_AND_LED
- 1
ILS
+ 7
-
+
BUTTON
FBW_RMP_MODE_BUTTON_AND_LED
- 1
MLS
+ 8
BUTTON
FBW_RMP_MODE_BUTTON_AND_LED
- 1
ADF
+ 9
@@ -258,6 +261,7 @@
FBW_RMP_MODE_BUTTON_AND_LED
1
BFO
+ 10
@@ -303,9 +307,10 @@
let modeId = #MODE_ID, number#;
alias toggleSwitch = (L:A32NX_RMP_#SIDE#_TOGGLE_SWITCH, bool);
alias selectedMode = (L:A32NX_RMP_#SIDE#_SELECTED_MODE, number);
+ alias navButtonPressed = (L:A32NX_RMP_#SIDE#_NAV_BUTTON_SELECTED, bool);
alias annunciatorLight = (L:A32NX_OVHD_INTLT_ANN, number);
let emissiveDim = if annunciatorLight == 2 { 0.05 } else { 1 };
- (if ((!inop and toggleSwitch and (selectedMode == modeId)) or (annunciatorLight == 0)) and indicatorsPowered {
+ (if ((!inop and toggleSwitch and ((selectedMode == modeId) or (modeId == 12 and navButtonPressed))) or (annunciatorLight == 0)) and indicatorsPowered {
1 * emissiveDim
} else {
0
diff --git a/src/fmgc/src/radionav/NavRadioManager.ts b/src/fmgc/src/radionav/NavRadioManager.ts
index f3cc3cc22f0..60ae4b15763 100644
--- a/src/fmgc/src/radionav/NavRadioManager.ts
+++ b/src/fmgc/src/radionav/NavRadioManager.ts
@@ -8,19 +8,40 @@ export enum TuningMode {
* This is a placeholder for the new radio nav tuning logic... coming soon to an A32NX near you
*/
export class NavRadioManager {
- tuningMode1: TuningMode = TuningMode.Auto;
+ tuningMode: TuningMode = TuningMode.Auto;
- tuningMode2: TuningMode = TuningMode.Auto;
+ manualTuned: boolean;
- tuningMode3: TuningMode = TuningMode.Auto;
+ rmpTuned: boolean;
constructor(public _parentInstrument: BaseInstrument) {
- SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_1_TUNING_MODE', 'Enum', TuningMode.Manual);
- SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_2_TUNING_MODE', 'Enum', TuningMode.Manual);
- SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_3_TUNING_MODE', 'Enum', TuningMode.Manual);
+ SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'Enum', TuningMode.Auto);
}
- update(_: number): void {
- // Do nothing
+ public update(deltaTime: number, manualTuned: boolean, rmpTuned: boolean): void {
+ if (this.manualTuned !== manualTuned || this.rmpTuned !== rmpTuned) {
+ // too avoid SetSimVar too often
+ this.manualTuned = manualTuned;
+ this.rmpTuned = rmpTuned;
+
+ if (manualTuned) {
+ this.tuningMode = TuningMode.Manual;
+ } else if (rmpTuned) {
+ this.tuningMode = TuningMode.Remote;
+ } else {
+ if (this.tuningMode === TuningMode.Remote) {
+ // Happens when NAV push button is pushed back
+ // It resets all the frequencies (real life behavior)
+ SimVar.SetSimVarValue('K:ADF_ACTIVE_SET', 'Frequency ADF BCD32', 0);
+ SimVar.SetSimVarValue('K:ADF2_ACTIVE_SET', 'Frequency ADF BCD32', 0);
+ SimVar.SetSimVarValue('K:NAV1_RADIO_SET_HZ', 'Hz', 0);
+ SimVar.SetSimVarValue('K:NAV2_RADIO_SET_HZ', 'Hz', 0);
+ SimVar.SetSimVarValue('K:NAV3_RADIO_SET_HZ', 'Hz', 0);
+ }
+
+ this.tuningMode = TuningMode.Auto;
+ }
+ SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'Enum', this.tuningMode);
+ }
}
}
diff --git a/src/instruments/src/ND/elements/RadioNavInfo.tsx b/src/instruments/src/ND/elements/RadioNavInfo.tsx
index 31439bcd2bc..470be92d558 100644
--- a/src/instruments/src/ND/elements/RadioNavInfo.tsx
+++ b/src/instruments/src/ND/elements/RadioNavInfo.tsx
@@ -11,11 +11,11 @@ export enum NavAidMode {
export type RadioNavInfoProps = { index: 1 | 2, side: EfisSide }
-const TuningModeIndicator: React.FC<{ index: 1 | 2, frequency: number }> = ({ index, frequency }) => {
- const [tuningMode] = useSimVar(`L:A32NX_FMGC_RADIONAV_${index}_TUNING_MODE`, 'enum');
+const TuningModeIndicator: React.FC<{ index: 1 | 2 }> = ({ index }) => {
+ const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum');
return (
- frequency > 1 && tuningMode !== TuningMode.Auto && (
+ tuningMode !== TuningMode.Auto && (
{tuningMode === TuningMode.Manual ? 'M' : 'R'}
) || null
);
@@ -81,7 +81,7 @@ const VorInfo: React.FC<{index: 1 | 2}> = ({ index }) => {
20 ? x + 46 : x + 58} y={759} fontSize={24} fill="#00ff00" textAnchor="end">{dmeText}
NM
-
+
);
};
@@ -108,14 +108,13 @@ const AdfInfo: React.FC<{index: 1 | 2}> = ({ index }) => {
ADF
{index}
- {adfAvailable ? adfIdent : adfFrequency.toFixed(0)}
{adfAvailable && (
{adfIdent}
)}
- {!adfAvailable && (
+ {!adfAvailable && adfFrequency > 0 && (
{Math.floor(adfFrequency).toFixed(0)}
)}
-
+
);
};
diff --git a/src/instruments/src/ND/pages/RoseMode.tsx b/src/instruments/src/ND/pages/RoseMode.tsx
index ed237365791..408106b7464 100644
--- a/src/instruments/src/ND/pages/RoseMode.tsx
+++ b/src/instruments/src/ND/pages/RoseMode.tsx
@@ -776,7 +776,7 @@ const VorInfo: FC<{side: EfisSide}> = memo(({ side }) => {
const [vorIdent] = useSimVar(`NAV IDENT:${index}`, 'string');
const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz');
const [vorCourse] = useSimVar(`NAV OBS:${index}`, 'degrees');
- const [tuningMode] = useSimVar(`L:A32NX_FMGC_RADIONAV_${index}_TUNING_MODE`, 'enum');
+ const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum');
const [vorAvailable] = useSimVar(`NAV HAS NAV:${index}`, 'boolean');
const [freqInt, freqDecimal] = vorFrequency.toFixed(2).split('.', 2);
@@ -806,7 +806,7 @@ const VorInfo: FC<{side: EfisSide}> = memo(({ side }) => {
{vorCourse >= 0 ? (`${Math.round(vorCourse)}`).padStart(3, '0') : '---'}
°
- { vorFrequency > 0 && {tuningModeLabel} }
+ {tuningModeLabel}
{vorIdent}
);
@@ -816,7 +816,7 @@ const IlsInfo: FC = memo(() => {
const [ilsIdent] = useSimVar('NAV IDENT:3', 'string');
const [ilsFrequency] = useSimVar('NAV ACTIVE FREQUENCY:3', 'megahertz');
const [ilsCourse] = useSimVar('NAV LOCALIZER:3', 'degrees');
- const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_3_TUNING_MODE', 'enum');
+ const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum');
const [locAvailable] = useSimVar('L:A32NX_RADIO_RECEIVER_LOC_IS_VALID', 'number');
const [freqInt, freqDecimal] = ilsFrequency.toFixed(2).split('.', 2);
@@ -843,7 +843,7 @@ const IlsInfo: FC = memo(() => {
{locAvailable ? (`${Math.round(ilsCourse)}`).padStart(3, '0') : '---'}
°
- { ilsFrequency > 0 && {tuningModeLabel} }
+ {tuningModeLabel}
{ilsIdent}
);
diff --git a/src/instruments/src/PFD/HeadingIndicator.tsx b/src/instruments/src/PFD/HeadingIndicator.tsx
index f7d00bf78c5..5b6c9df264e 100644
--- a/src/instruments/src/PFD/HeadingIndicator.tsx
+++ b/src/instruments/src/PFD/HeadingIndicator.tsx
@@ -312,7 +312,8 @@ class QFUIndicator extends DisplayComponent<{ ILSCourse: Subscribable, h
this.props.lsPressed.sub((ls) => {
this.lsPressed = ls;
- if (ls) {
+ // ilsCourse may be negative if tuned via the RMP then back to MCDU
+ if (ls && this.ilsCourse >= 0) {
this.qfuContainer.instance.classList.remove('HiddenElement');
} else {
this.qfuContainer.instance.classList.add('HiddenElement');
diff --git a/src/instruments/src/PFD/LandingSystemIndicator.tsx b/src/instruments/src/PFD/LandingSystemIndicator.tsx
index 96c87d480d7..8aa7028d81c 100644
--- a/src/instruments/src/PFD/LandingSystemIndicator.tsx
+++ b/src/instruments/src/PFD/LandingSystemIndicator.tsx
@@ -118,6 +118,8 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> {
private dme = 0;
+ private rmpTuned = false;
+
private dmeVisibilitySub = Subject.create('hidden');
private destRef = FSComponent.createRef();
@@ -157,6 +159,11 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> {
this.dme = dme;
this.updateContents();
});
+
+ sub.on('ilsRMPTuned').whenChanged().handle((rmpTuned) => {
+ this.rmpTuned = rmpTuned;
+ this.updateContents();
+ });
}
private updateContents() {
@@ -170,7 +177,7 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> {
let distLeading = '';
let distTrailing = '';
- if (this.hasDme) {
+ if (this.hasDme && !this.rmpTuned) {
this.dmeVisibilitySub.set('display: inline');
const dist = Math.round(this.dme * 10) / 10;
diff --git a/src/instruments/src/PFD/instrument.tsx b/src/instruments/src/PFD/instrument.tsx
index ce457e278df..b2a266a44a1 100644
--- a/src/instruments/src/PFD/instrument.tsx
+++ b/src/instruments/src/PFD/instrument.tsx
@@ -133,6 +133,7 @@ class A32NX_PFD extends BaseInstrument {
this.simVarPublisher.subscribe('selectedFpa');
this.simVarPublisher.subscribe('targetSpeedManaged');
this.simVarPublisher.subscribe('ilsCourse');
+ this.simVarPublisher.subscribe('ilsRMPTuned');
this.simVarPublisher.subscribe('tla1');
this.simVarPublisher.subscribe('tla2');
this.simVarPublisher.subscribe('metricAltToggle');
diff --git a/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx b/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx
index 8863473e484..c2b0d1abb67 100644
--- a/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx
+++ b/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx
@@ -68,6 +68,7 @@ export interface PFDSimvars {
groundTrackTrue: number;
selectedFpa: number;
ilsCourse: number;
+ ilsRMPTuned: boolean;
metricAltToggle: boolean;
tla1: number;
tla2: number;
@@ -225,6 +226,7 @@ export enum PFDVars {
groundTrackTrue = 'GPS GROUND TRUE TRACK',
selectedFpa = 'L:A32NX_AUTOPILOT_FPA_SELECTED',
ilsCourse = 'L:A32NX_FM_LS_COURSE',
+ ilsRMPTuned = 'L:A32NX_RMP_ILS_TUNED',
metricAltToggle = 'L:A32NX_METRIC_ALT_TOGGLE',
tla1='L:A32NX_AUTOTHRUST_TLA:1',
tla2='L:A32NX_AUTOTHRUST_TLA:2',
@@ -383,6 +385,7 @@ export class PFDSimvarPublisher extends SimVarPublisher {
['groundTrackTrue', { name: PFDVars.groundTrackTrue, type: SimVarValueType.Degree }],
['selectedFpa', { name: PFDVars.selectedFpa, type: SimVarValueType.Degree }],
['ilsCourse', { name: PFDVars.ilsCourse, type: SimVarValueType.Number }],
+ ['ilsRMPTuned', { name: PFDVars.ilsRMPTuned, type: SimVarValueType.Bool }],
['metricAltToggle', { name: PFDVars.metricAltToggle, type: SimVarValueType.Bool }],
['tla1', { name: PFDVars.tla1, type: SimVarValueType.Number }],
['tla2', { name: PFDVars.tla2, type: SimVarValueType.Number }],
diff --git a/src/instruments/src/RMP/Components/BaseRadioPanels.tsx b/src/instruments/src/RMP/Components/BaseRadioPanels.tsx
index 7037175bd05..c9860e88961 100644
--- a/src/instruments/src/RMP/Components/BaseRadioPanels.tsx
+++ b/src/instruments/src/RMP/Components/BaseRadioPanels.tsx
@@ -1,7 +1,9 @@
-import React from 'react';
+import React, { useState } from 'react';
import { useSimVar, useInteractionSimVar } from '@instruments/common/simVars';
import { useInteractionEvent } from '@instruments/common/hooks';
+import { TransceiverType } from './StandbyFrequency';
import { VhfRadioPanel } from './VhfRadioPanel';
+import { NavRadioPanel } from './NavRadioPanel';
import { RadioPanelDisplay } from './RadioPanelDisplay';
interface Props {
@@ -44,21 +46,90 @@ const UnpoweredRadioPanel = () => (
* Renders appropriate mode sub-component (e.g. VhfRadioPanel).
*/
const PoweredRadioPanel = (props: Props) => {
+ const [navTransceiverType, setNavTransceiverType] = useState(TransceiverType.RADIO_VHF);
+
+ // Used to turn on the associated led
const [panelMode, setPanelMode] = useSimVar(`L:A32NX_RMP_${props.side}_SELECTED_MODE`, 'Number', 250);
+ // Used to determine (in the FGMC for instance) if the system is in NAV backup mode. L and R simvars have to be checked
+ const [navButtonPressed, setNavButton] = useSimVar(`L:A32NX_RMP_${props.side}_NAV_BUTTON_SELECTED`, 'boolean', 250);
+ // Used to return to the selected VHF once NAV is pushed again
+ const [previousPanelMode, setPreviousPanelMode] = useState(panelMode);
// Hook radio management panel mode buttons to set panelMode SimVar.
- useInteractionEvent(`A32NX_RMP_${props.side}_VHF1_BUTTON_PRESSED`, () => setPanelMode(1));
- useInteractionEvent(`A32NX_RMP_${props.side}_VHF2_BUTTON_PRESSED`, () => setPanelMode(2));
- useInteractionEvent(`A32NX_RMP_${props.side}_VHF3_BUTTON_PRESSED`, () => setPanelMode(3));
+ useInteractionEvent(`A32NX_RMP_${props.side}_VHF1_BUTTON_PRESSED`, () => {
+ setPanelMode(1);
+ setPreviousPanelMode(1);
+ setNavTransceiverType(TransceiverType.RADIO_VHF);
+ });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_VHF2_BUTTON_PRESSED`, () => {
+ setPanelMode(2);
+ setPreviousPanelMode(2);
+ setNavTransceiverType(TransceiverType.RADIO_VHF);
+ });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_VHF3_BUTTON_PRESSED`, () => {
+ setPanelMode(3);
+ setPreviousPanelMode(3);
+ setNavTransceiverType(TransceiverType.RADIO_VHF);
+ });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_NAV_BUTTON_PRESSED`, () => {
+ if (navButtonPressed) {
+ setPanelMode(previousPanelMode);
+ setNavTransceiverType(TransceiverType.RADIO_VHF);
+ }
+
+ setNavButton(!navButtonPressed);
+ });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_VOR_BUTTON_PRESSED`, () => {
+ if (navButtonPressed) {
+ setPanelMode(6);
+ setNavTransceiverType(TransceiverType.VOR);
+ }
+ });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_ILS_BUTTON_PRESSED`, () => {
+ if (navButtonPressed) {
+ setPanelMode(7);
+ setNavTransceiverType(TransceiverType.ILS);
+ }
+ });
+
+ /**
+ * MLS IMPLEMENTED IN THE XML BEHAVIOURS
+ * BUT DISABLED HERE SINCE THERE IS NOT ENOUGH REFERENCES
+ */
+ // useInteractionEvent(`A32NX_RMP_${props.side}_MLS_BUTTON_PRESSED`, () => {
+ // if (navButtonPressed) {
+ // setPanelMode(8);
+ // setNavTransceiverType(TransceiverType.ILS);
+ // }
+ // });
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_ADF_BUTTON_PRESSED`, () => {
+ if (navButtonPressed) {
+ setPanelMode(9);
+ setNavTransceiverType(TransceiverType.ADF);
+ }
+ });
// This means we're in a VHF communications mode.
- if (panelMode === 1 || panelMode === 2 || panelMode === 3) return ();
-
- // If we reach this block, something's gone wrong. We'll just render a broken panel.
- return (
-
-
-
-
- );
+ switch (navTransceiverType) {
+ case TransceiverType.RADIO_VHF:
+ return ();
+ case TransceiverType.VOR:
+ case TransceiverType.ILS:
+ case TransceiverType.ADF:
+ return ();
+ default:
+ // If we reach this block, something's gone wrong. We'll just render a broken panel.
+ return (
+
+
+
+
+ );
+ }
};
diff --git a/src/instruments/src/RMP/Components/NavRadioPanel.tsx b/src/instruments/src/RMP/Components/NavRadioPanel.tsx
new file mode 100644
index 00000000000..b6351eda774
--- /dev/null
+++ b/src/instruments/src/RMP/Components/NavRadioPanel.tsx
@@ -0,0 +1,163 @@
+import React, { useEffect, useState } from 'react';
+
+import { StandbyFrequency, TransceiverType } from './StandbyFrequency';
+import { StandbyCourse } from './StandbyCourse';
+import { useSimVar } from '../../Common/simVars';
+import { RadioPanelDisplay } from './RadioPanelDisplay';
+import { useInteractionEvent } from '../../Common/hooks';
+
+interface Props {
+ /**
+ * The RMP side (e.g. 'L' or 'R').
+ */
+ side: string,
+
+ /**
+ * The NAV transceiver (VOR, ILS, ADF).
+ */
+ transceiver: number,
+
+}
+
+enum Mode {
+ FREQUENCY = 0,
+ COURSE = 1
+}
+
+/*
+* Had to use this simvars to save the frequencies set via the RMP
+* In real life, if you tune a navaid via the MCDU and then press NAV, the frequency is not the same
+/
+
+/**
+ *
+ * @param transceiver The transceiver type (VOR, ADF or ILS)
+ * @param side Side on which the transceiver is (L or R)
+ * @returns a tuble simvar
+ */
+const useActiveFrequency = (transceiver: number, side: string) => {
+ switch (transceiver) {
+ case TransceiverType.VOR:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_VOR`, 'number');
+ case TransceiverType.ADF:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_ADF`, 'number');
+ default:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_ILS`, 'number');
+ }
+};
+
+/**
+ *
+ * @param transceiver The transceiver type (VOR, ADF or ILS)
+ * @param side Side on which the transceiver is (L or R)
+ * @returns a tuble simvar
+ */
+const useStandbyFrequency = (transceiver: number, side: string) => {
+ switch (transceiver) {
+ case TransceiverType.VOR:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_VOR`, 'number');
+ case TransceiverType.ADF:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_ADF`, 'number');
+ default:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_ILS`, 'number');
+ }
+};
+
+/**
+ *
+ * @param transceiver The transceiver type (VOR, ADF or ILS)
+ * @param side Side on which the transceiver is (L or R)
+ * @returns a tuble simvar
+ */
+const useCourse = (transceiver: number, side: string) => {
+ switch (transceiver) {
+ case TransceiverType.VOR:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_COURSE_VOR`, 'number');
+ default:
+ return useSimVar(`L:A32NX_RMP_${side}_SAVED_COURSE_ILS`, 'number');
+ }
+};
+
+const setActiveFrequencySimVar = (transceiver: number, index: number, frequency: number) => {
+ if (transceiver === TransceiverType.ADF) {
+ SimVar.SetSimVarValue(`K:ADF${index === 1 ? '' : index}_ACTIVE_SET`, 'Frequency ADF BCD32', Avionics.Utils.make_adf_bcd32(frequency));
+ }
+
+ SimVar.SetSimVarValue(`K:NAV${index}_RADIO_SET_HZ`, 'Hz', frequency);
+};
+
+/**
+ * NAV radio management panel React component.
+ * Hooks into the mode active and standby frequency SimVars and wires transfer button.
+ * Renders active frequency RadioPanelDisplay and appropriate StandbyFrequency sub-components.
+ */
+export const NavRadioPanel = (props: Props) => {
+ let standbyWindow: JSX.Element;
+
+ let index = props.side === 'L' ? 1 : 2;
+ if (props.transceiver === TransceiverType.ILS) {
+ index = 3; // Both RMPs manage the same ILS
+ }
+
+ const [mode, setMode] = useState(Mode.FREQUENCY);
+
+ const [activeFrequency, setActiveFrequencySaved] = useActiveFrequency(props.transceiver, props.side);
+ const [standbyFrequency, setStandbyFrequencySaved] = useStandbyFrequency(props.transceiver, props.side);
+ const [course, setCourseSaved] = useCourse(props.transceiver, props.side);
+
+ const [, setCourse] = useSimVar(props.transceiver === TransceiverType.VOR ? `K:VOR${index}_SET` : 'L:A32NX_FM_LS_COURSE', 'number', 100);
+
+ const [APPR] = useSimVar('L:A32NX_FCU_APPR_MODE_ACTIVE', 'bool');
+ const [AP] = useSimVar('L:A32NX_AUTOPILOT_ACTIVE', 'bool');
+ const [RA1] = useSimVar('L:A32NX_RA_1_RADIO_ALTITUDE', 'number');
+ const [RA2] = useSimVar('L:A32NX_RA_2_RADIO_ALTITUDE', 'number');
+
+ useInteractionEvent(`A32NX_RMP_${props.side}_TRANSFER_BUTTON_PRESSED`, () => {
+ // Inhibit RMP tuning if below 700 RA, APPR engaged, at least one AP/FD engaged (FCOM compliant)
+ if ((RA1 >= 700 && RA2 >= 700) || !APPR || !AP) {
+ if (mode === Mode.FREQUENCY) {
+ if (props.transceiver !== TransceiverType.ADF) {
+ setMode(Mode.COURSE);
+ }
+
+ // FCOM compliant: Both RMPs must be in nav backup mode in order to tune the ILS
+ if (props.transceiver !== TransceiverType.ILS
+ || (SimVar.GetSimVarValue('L:A32NX_RMP_L_NAV_BUTTON_SELECTED', 'Bool')
+ && SimVar.GetSimVarValue('L:A32NX_RMP_R_NAV_BUTTON_SELECTED', 'Bool'))) {
+ setActiveFrequencySimVar(props.transceiver, index, standbyFrequency);
+ }
+ setActiveFrequencySaved(standbyFrequency);
+
+ if (props.transceiver === TransceiverType.ILS) {
+ SimVar.SetSimVarValue('L:A32NX_RMP_ILS_TUNED', 'boolean', true);
+ }
+ } else {
+ setCourse(course);
+ setMode(Mode.FREQUENCY);
+ }
+ }
+ });
+
+ // This effect to display frequency mode instead of course mode when switching between receivers.
+ // After few debug sessions, it was noticed standbyFrequency was the first valuable sign of switch.
+ // I could have listened props.transceiver but this caused flickering (very fast display of previous frequency) due to sequential render
+ useEffect(() => {
+ // Performance purpose. Could set Frequency everytime but setMode fires a render
+ if (mode === Mode.COURSE) {
+ setMode(Mode.FREQUENCY);
+ }
+ }, [standbyFrequency]);
+
+ if (mode === Mode.FREQUENCY) {
+ standbyWindow = ;
+ } else {
+ standbyWindow = ;
+ }
+
+ return (
+
+
+ {standbyWindow}
+
+ );
+};
diff --git a/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx b/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx
index a2ada050a57..e44f5be801a 100644
--- a/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx
+++ b/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx
@@ -15,7 +15,17 @@ const TEXT_DATA_MODE_VHF3 = 'DATA';
* @param frequency The given frequency number in Hz.
* @returns The formated frequency string in 123.456
*/
-const formatFrequency = (frequency: number): string => (frequency / 1000000).toFixed(3).padEnd(7, '0');
+const formatFrequency = (frequency: number): string => {
+ // VHF COM, VOR, ILS
+ if (frequency >= 108000000) {
+ return (frequency / 1000000).toFixed(3).padEnd(7, '0');
+ }
+
+ // HF HERE
+
+ // ADF
+ return (frequency / 1000).toFixed(1);
+};
/**
* Radio management panel seven-segment frequency/course display.
@@ -33,18 +43,16 @@ export function RadioPanelDisplay(props: Props) {
8.8.8.8.8.8
);
+ } else if ((typeof props.value === 'string')) {
+ content = (
+
+ {props.value}
+
+ );
} else if (props.value > 0) {
- let value = '';
- // If the passed value prop is a number, we'll use formatFrequency to get string format.
- if (typeof props.value === 'number') {
- value = formatFrequency(props.value);
- } else {
- value = props.value;
- }
-
content = (
- {value}
+ {formatFrequency(props.value)}
);
} else {
diff --git a/src/instruments/src/RMP/Components/StandbyCourse.tsx b/src/instruments/src/RMP/Components/StandbyCourse.tsx
new file mode 100644
index 00000000000..e0d1bc9f5fb
--- /dev/null
+++ b/src/instruments/src/RMP/Components/StandbyCourse.tsx
@@ -0,0 +1,44 @@
+import React, { useCallback, useRef } from 'react';
+import { RadioPanelDisplay } from './RadioPanelDisplay';
+import { useInteractionEvent } from '../../Common/hooks';
+import { RateMultiplierKnob, UpdateValueCallback } from '../../Common/RateMultiplierKnob';
+
+interface Props {
+ /**
+ * The RMP side (e.g. 'L' or 'R').
+ */
+ side: string,
+
+ /**
+ * The current standby frequency value in Hz.
+ */
+ value: number,
+
+ /**
+ * A callback to set the current standby frequency value in Hz.
+ */
+ setValue: (x: any) => void,
+}
+
+/**
+ * Standby frequency radio management panel React component.
+ * Hooks to outer and inner rotary encoder knobs.
+ * Renders standby frequency RadioPanelDisplay sub-component.
+ */
+export const StandbyCourse = (props: Props) => {
+ // Handle inner knob turned.
+ const innerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => {
+ const integer = Math.floor((props.value + offset) / 360);
+ props.setValue(props.value - (integer * 360) + offset);
+ }, [props.value]);
+
+ // Used to change decimal value of freq.
+ const innerKnob = useRef(new RateMultiplierKnob(200, 1));
+ innerKnob.current.updateValue = innerKnobUpdateCallback;
+
+ // Hook rotation events from simulator to custom knob class methods.
+ useInteractionEvent(`A32NX_RMP_${props.side}_INNER_KNOB_TURNED_CLOCKWISE`, () => innerKnob.current.increase());
+ useInteractionEvent(`A32NX_RMP_${props.side}_INNER_KNOB_TURNED_ANTICLOCKWISE`, () => innerKnob.current.decrease());
+
+ return ();
+};
diff --git a/src/instruments/src/RMP/Components/StandbyFrequency.tsx b/src/instruments/src/RMP/Components/StandbyFrequency.tsx
index 6b2e46fc21e..d3500811852 100644
--- a/src/instruments/src/RMP/Components/StandbyFrequency.tsx
+++ b/src/instruments/src/RMP/Components/StandbyFrequency.tsx
@@ -6,6 +6,13 @@ import { RateMultiplierKnob, UpdateValueCallback } from '../../Common/RateMultip
declare const Utils; // this can also be replaced once /typings are available
+export enum TransceiverType {
+ RADIO_VHF,
+ VOR,
+ ILS,
+ ADF
+}
+
interface Props {
/**
* The RMP side (e.g. 'L' or 'R').
@@ -17,6 +24,11 @@ interface Props {
*/
value: number,
+ /**
+ * Type of transceiver (e.g VHF, HF, VOR, ILS, MLS, ADF)
+ */
+ transceiver: TransceiverType,
+
/**
* A callback to set the current standby frequency value in Hz.
*/
@@ -37,6 +49,7 @@ const findNearestInArray = (value: number, array: number[]): number => array.red
* High Frequency communications use 10 kHz spacing.
* Vatsim VHF communications use 25 kHz spacing.
* VOR / ILS frequencies use 50 kHz spacing.
+ * ADF frequencies use 1kHz spacing.
*/
type ChannelSpacing = 8.33 | 10 | 25 | 50;
@@ -63,7 +76,7 @@ const offsetFrequencyChannel = (spacing: ChannelSpacing, channel: number, offset
// Special cases, such as ADF, do not use the ending algorithm to find frequencies.
if (endings === null) {
- return (Math.floor(channel / 100) + spacing * offset) * 100;
+ return (Math.floor(channel % 100) + spacing * offset);
}
// Reverse the channel order if we're going backwards.
@@ -100,17 +113,47 @@ const offsetFrequencyChannel = (spacing: ChannelSpacing, channel: number, offset
* Renders standby frequency RadioPanelDisplay sub-component.
*/
export const StandbyFrequency = (props: Props) => {
- const spacing = usePersistentProperty('RMP_VHF_SPACING_25KHZ', '0')[0] === '0' ? 8.33 : 25;
+ let spacing: ChannelSpacing;
+ let toMhz = 1000;
+
+ switch (props.transceiver) {
+ case TransceiverType.ILS:
+ spacing = 25;
+ break;
+ case TransceiverType.VOR:
+ spacing = 50;
+ break;
+ case TransceiverType.ADF:
+ toMhz = 1;
+ break;
+ default:
+ spacing = usePersistentProperty('RMP_VHF_SPACING_25KHZ', '0')[0] === '0' ? 8.33 : 25;
+ }
+
// Handle outer knob turned.
const outerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => {
if (props.value !== 0) {
- const frequency = Math.round(props.value / 1000);
- const integer = Math.floor(frequency / 1000);
- const decimal = frequency % 1000;
+ let frequency = props.value;
+
+ if (props.transceiver !== TransceiverType.ADF) {
+ frequency = Math.round(frequency / 1000); // To kHz
+ }
+
+ const integer = Math.floor(frequency / 1000) + offset;
+
// @todo determine min/max depending on mode.
- const maxInteger = decimal > 975 ? 135 : 136;
- const newInteger = Utils.Clamp(integer + offset, 118, maxInteger);
- props.setValue((newInteger * 1000 + decimal) * 1000);
+ let newInteger = 0;
+ if (props.transceiver === TransceiverType.RADIO_VHF) {
+ newInteger = Utils.Clamp(integer, 118, 136);
+ } else if (props.transceiver === TransceiverType.ILS) {
+ newInteger = Utils.Clamp(integer, 108, 111);
+ } else if (props.transceiver === TransceiverType.VOR) {
+ newInteger = Utils.Clamp(integer, 108, 117);
+ } else if (props.transceiver === TransceiverType.ADF) {
+ newInteger = Utils.Clamp(integer, 190, 1750);
+ }
+
+ props.setValue((newInteger * 1000 + frequency % 1000) * toMhz);
} else {
props.setValue(0);
}
@@ -118,18 +161,25 @@ export const StandbyFrequency = (props: Props) => {
// Handle inner knob turned.
const innerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => {
- const frequency = Math.round(props.value / 1000);
if (props.value !== 0) {
- const integer = Math.floor(frequency / 1000);
- // @todo determine correct frequency spacing depending on mode.
- const decimal = offsetFrequencyChannel(spacing, frequency % 1000, offset);
- // @todo determine min/max depending on mode.
+ let frequency = props.value;
+
+ if (props.transceiver !== TransceiverType.ADF) {
+ frequency = Math.round(frequency / 1000); // To kHz
+ }
+
// Tested in real life:
// Integer cannot return to 118 from 136 to the right
// Decimal can return to 0 from 975 to the right
- // const maxDecimal = integer === 136 ? 975 : 1000;
- const newDecimal = Utils.Clamp(decimal, 0, 1000);
- props.setValue((integer * 1000 + newDecimal) * 1000);
+ const integer = Math.floor(frequency / 1000);
+ let decimal = 0;
+
+ if (props.transceiver !== TransceiverType.ADF) {
+ decimal = offsetFrequencyChannel(spacing, frequency % 1000, offset);
+ } else { // offsetFrequencyChannel does not fit ADF needs
+ decimal = frequency % 1000 === 0 ? 500 : 0;
+ }
+ props.setValue((integer * 1000 + decimal % 1000) * toMhz);
} else {
props.setValue(0);
}
diff --git a/src/instruments/src/RMP/Components/VhfRadioPanel.tsx b/src/instruments/src/RMP/Components/VhfRadioPanel.tsx
index 8e358d309b6..f1559cd09f0 100644
--- a/src/instruments/src/RMP/Components/VhfRadioPanel.tsx
+++ b/src/instruments/src/RMP/Components/VhfRadioPanel.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { StandbyFrequency } from './StandbyFrequency';
+import { StandbyFrequency, TransceiverType } from './StandbyFrequency';
import { useSplitSimVar } from '../../Common/simVars';
import { RadioPanelDisplay } from './RadioPanelDisplay';
import { useInteractionEvent } from '../../Common/hooks';
@@ -13,7 +13,7 @@ interface Props {
/**
* The VHF transceiver mode (VHF 1, 2, or 3).
*/
- transceiver: number,
+ vhf: number,
}
/**
@@ -56,15 +56,15 @@ const useStandbyVhfFrequency = (side: string, transceiver: number) => {
* Renders active frequency RadioPanelDisplay and appropriate StandbyFrequency sub-components.
*/
export const VhfRadioPanel = (props: Props) => {
- const [active, setActive] = useActiveVhfFrequency(props.transceiver);
- const [standby, setStandby] = useStandbyVhfFrequency(props.side, props.transceiver);
+ const [active, setActive] = useActiveVhfFrequency(props.vhf);
+ const [standby, setStandby] = useStandbyVhfFrequency(props.side, props.vhf);
const [, setValueOppositePanelStandby] = props.side === 'L' ? useStandbyVhfFrequency('R', 3) : useStandbyVhfFrequency('L', 3);
// Handle Transfer Button Pressed.
useInteractionEvent(`A32NX_RMP_${props.side}_TRANSFER_BUTTON_PRESSED`, () => {
// Force the standby opposite side otherwise we would lose the frequency/data format
// Otherwise it would become frequency/frequency
- if (props.transceiver === 3) {
+ if (props.vhf === 3) {
setValueOppositePanelStandby(active);
}
setActive(standby);
@@ -74,7 +74,7 @@ export const VhfRadioPanel = (props: Props) => {
return (
-
+
);
};