From 1db48daccbf46ddd542a3f43933705122488a915 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 29 May 2019 17:31:25 +0100 Subject: [PATCH] ATC: add transponder system (#93) * ATC: add transponder system * I know you want to be but you are not a RMP, ATC * Update atc.nas * Update A320-main.xml * fix * Disable radios in menubar, change TCAS mode according to transponder switch * Add new TCAS flags, will be uncommented in 2019.3 * Fix * Fix * Hook TCAS to electrical system * Fix * Resetting after failure * Fix * electrical output now controlled by transponder itself * Fix * fix * fix * Fix * Fix * Bugfixes, add to acconfig * Re-add radio dialog * Prevent radio dialog from modifying mode * Fix clear display * Remove conflict between dialog and setting the code on the panel * VC: Cleanup transponder bindings * Fixes * Fix * Fix finally * Transponder: realign --- A320-main.xml | 13 +- AircraftConfig/acconfig.nas | 6 + Models/FlightDeck/a320.flightdeck.xml | 18 + .../Instruments/Pedestal_up/Pedestal_up.xml | 322 +++++++++++++++++- Nasal/atc.nas | 245 +++++++++++++ Nasal/electrical.nas | 2 - Nasal/libraries.nas | 1 + Systems/instrumentation.xml | 9 + 8 files changed, 612 insertions(+), 4 deletions(-) create mode 100644 Nasal/atc.nas diff --git a/A320-main.xml b/A320-main.xml index 3e897829..fceba4fa 100644 --- a/A320-main.xml +++ b/A320-main.xml @@ -568,6 +568,10 @@ false 0 + + 0 + 0 + 0 0 @@ -767,6 +771,10 @@ 0 + + 2000 + 0 + 0 @@ -972,7 +980,7 @@ true - 3 + 1 Sounds/tcas/female/ @@ -1563,6 +1571,9 @@ Aircraft/IDG-A32X/Nasal/acp.nas + + Aircraft/IDG-A32X/Nasal/atc.nas + diff --git a/AircraftConfig/acconfig.nas b/AircraftConfig/acconfig.nas index e02cd7c5..a332d690 100644 --- a/AircraftConfig/acconfig.nas +++ b/AircraftConfig/acconfig.nas @@ -266,6 +266,8 @@ var colddark = func { setprop("/controls/lighting/taxi-light-switch", 0.0); setprop("/controls/switches/landing-lights-l", 0.0); setprop("/controls/switches/landing-lights-r", 0.0); + setprop("/controls/atc/mode-knob", 0); + atc.transponderPanel.modeSwitch(1); libraries.systemsInit(); failReset(); if (getprop("/engines/engine[1]/n2-actual") < 2) { @@ -447,6 +449,8 @@ var taxi_b = func { setprop("/controls/radio/rmp[0]/on", 1); setprop("/controls/radio/rmp[1]/on", 1); setprop("/controls/radio/rmp[2]/on", 1); + setprop("/controls/atc/mode-knob", 2); + atc.transponderPanel.modeSwitch(3); setprop("/systems/fadec/power-avail", 1); setprop("/systems/fadec/powered-time", -310); setprop("/controls/lighting/turnoff-light-switch", 1); @@ -495,6 +499,8 @@ var takeoff = func { setprop("/controls/flight/flap-lever", 1); setprop("/controls/flight/flap-pos", 2); setprop("/controls/flight/flap-txt", "1+F"); + setprop("/controls/atc/mode-knob", 4); + atc.transponderPanel.modeSwitch(5); libraries.flaptimer.start(); setprop("/controls/flight/elevator-trim", -0.07); systems.arm_autobrake(3); diff --git a/Models/FlightDeck/a320.flightdeck.xml b/Models/FlightDeck/a320.flightdeck.xml index 0e6c4a65..dc1911ff 100644 --- a/Models/FlightDeck/a320.flightdeck.xml +++ b/Models/FlightDeck/a320.flightdeck.xml @@ -350,6 +350,8 @@ arpt_led arpt_led.001 a-thr_led + atc-code + atc-test audio_att_led audio_att_sgn audio_call_hf2_led @@ -443,11 +445,25 @@ + + select + atc-code + + + + controls/switches/annun-test + 1 + + + + + select alt-text-test + atc-test audio_att_sgn audio_call_hf2_led audio_call_hf1_led @@ -5912,6 +5928,8 @@ hdg-text-test alt-text-test vs-text-test + atc-code + atc-test fpa-text qnh-inhg qnh-hpa diff --git a/Models/Instruments/Pedestal_up/Pedestal_up.xml b/Models/Instruments/Pedestal_up/Pedestal_up.xml index 56acbf9e..67446fa1 100644 --- a/Models/Instruments/Pedestal_up/Pedestal_up.xml +++ b/Models/Instruments/Pedestal_up/Pedestal_up.xml @@ -9,7 +9,23 @@ Panel lighting material + atc_0 + atc_1 + atc_2 + atc_3 + atc_4 + atc_5 + atc_6 + atc_7 + atc_abv atc_body + atc_clr + atc_fail + atc_ident + atc_screen + atc_stby + atc_sys + atc_thrt ecam_body ecam_switch_body engine_body @@ -79,7 +95,6 @@ radar_glare - Aircraft/IDG-A32X/Models/Effects/cockpit-irradiance ecam_body @@ -106,4 +121,309 @@ vu112_aids vu112_dfdr + + + Aircraft/IDG-A32X/Models/Effects/cockpit-irradiance + atc_0 + atc_1 + atc_2 + atc_3 + atc_4 + atc_5 + atc_6 + atc_7 + atc_abv + atc_body + atc_clr + atc_fail + atc_ident + atc_screen + atc_stby + atc_sys + atc_thrt + + + + atc-code + + -0.01279 + 0.20 + -0.13391 + 90 + + left-center + xy-plane + text-value + /systems/atc/transponder-code + %s + false + led.txf + true + false + false + 0.009 + + 32 + 32 + + + + + atc-test + + -0.01279 + 0.20 + -0.13391 + 90 + + left-center + xy-plane + literal + 8888 + led.txf + true + false + false + 0.009 + + 32 + 32 + + + + + pick + atc_0 + + + false + + nasal + + + + + + + pick + atc_1 + + + false + + nasal + + + + + + + pick + atc_2 + + + false + + nasal + + + + + + + pick + atc_3 + + + false + + nasal + + + + + + + pick + atc_4 + + + false + + nasal + + + + + + + pick + atc_5 + + + false + + nasal + + + + + + + pick + atc_6 + + + false + + nasal + + + + + + + pick + atc_7 + + + false + + nasal + + + + + + + pick + atc_clr + + + false + + nasal + + + + + + + rotate + atc_sys + -30 + 30 +
+ -0.003352 + 0.131446 + -0.13275 +
+ + 0 + 0 + 1 + + controls/atc/system-knob +
+ + + pick + atc_sys + + + + property-cycle + controls/atc/system-knob + 0 + 1 + + + nasal + + + + + + + rotate + atc_stby + -35 + 70 +
+ 0.01146 + 0.213663 + -0.13086 +
+ + 0 + 0 + 1 + + controls/atc/mode-knob +
+ + + pick + atc_stby + + + + + property-cycle + controls/atc/mode-knob + 0 + 1 + 2 + 3 + 4 + + + nasal + + + + + + + + property-cycle + controls/atc/mode-knob + 4 + 3 + 2 + 1 + 0 + + + nasal + + + + + + + pick + atc_ident + + + + nasal + + + + + + + select + atc_fail + + + systems/atc/failed + + systems/electrical/bus/dc-ess + 25 + + + + diff --git a/Nasal/atc.nas b/Nasal/atc.nas new file mode 100644 index 00000000..b58feeb8 --- /dev/null +++ b/Nasal/atc.nas @@ -0,0 +1,245 @@ +# A3XX ATC Panel +# Jonathan Redpath + +# Copyright (c) 2019 Jonathan Redpath + +var idCode = props.globals.getNode("/instrumentation/transponder/id-code", 1); + +var guiModes = ['OFF', 'STANDBY', 'TEST', 'GROUND', 'ON', 'ALTITUDE']; +var guiNode = props.globals.getNode("/sim/gui/dialogs/radios/transponder-mode", 1); +var forLoopFlag = 0; + +var Transponder = { + mode: 0, + code: "2000", + selected: 0, + electricalSrc: "", + activeADIRS: 0, + condition: 0, + failed: 0, + codeDigitsNodes: [props.globals.getNode("/instrumentation/transponder/inputs/digit[0]", 1), props.globals.getNode("/instrumentation/transponder/inputs/digit[1]", 1), props.globals.getNode("/instrumentation/transponder/inputs/digit[2]", 1), props.globals.getNode("/instrumentation/transponder/inputs/digit[3]", 1)], + serviceableNode: props.globals.getNode("/instrumentation/transponder/serviceable", 1), + knobNode: props.globals.getNode("instrumentation/transponder/inputs/knob-mode", 1), + identNode: props.globals.getNode("/instrumentation/transponder/inputs/ident-btn", 1), + wowNode: props.globals.getNode("/fdm/jsbsim/position/wow"), + ac1Node: props.globals.getNode("/systems/electrical/bus/ac1", 1), + tcasNode: props.globals.getNode("/instrumentation/tcas/inputs/mode"), + aglNode: props.globals.getNode("/position/gear-agl-ft", 1), + electricNode: props.globals.getNode("/systems/electrical/outputs/transponder", 1), + new: func(elecSrc, ADIRS) { + var t = {parents:[Transponder]}; + t.mode = 1; + t.code = "2000"; + t.selected = 0; + t.condition = 100; + t.failed = 0; + t.electricalSrc = props.globals.getNode(elecSrc, 1); + t.activeADIRS = ADIRS; + + return t; + }, + update: func() { + # TCAS - on seperate electrical source, so has to be before transponder electrical checking + if (me.ac1Node.getValue() < 110) { + me.tcasNode.setValue(0); # off + } else { + if (me.mode >= 1 and me.mode <= 3) { + me.tcasNode.setValue(1); # stby + } else if (me.mode == 4 or (me.mode == 5 and me.aglNode.getValue() < 1000)) { + me.tcasNode.setValue(2); # TA only + } else if (me.mode == 5) { + me.tcasNode.setValue(3); # TA/RA + } + } + + if (me.electricalSrc.getValue() > 110 and me.failed == 0) { + me.condition = 100; + transponderPanel.atcFailLight(0); + me.electricNode.setValue(28); + transponderPanel.modeSwitch(transponderPanel.modeSel); + } else { + me.condition = 0; + transponderPanel.atcFailLight(1); + me.setMode(0); # off + if (me.electricalSrc.getValue() < 110) { + me.electricNode.setValue(0); + } else { + me.electricNode.setValue(28); + } + } + + if (me.condition == 0 or me.selected != 1) { + return; + } + + if (me.mode == 1) { + if (me.knobNode.getValue() != 1) { + me.setMode(1); # stby + } + } else if (me.mode == 2) { + if (me.knobNode.getValue() != 4) { + me.setMode(4); # on + } + } else if (me.mode >= 3) { + if (me.wowNode.getBoolValue()) { + if (me.knobNode.getValue() != 3) { + me.setMode(3); # gnd + } + } else { + if (me.knobNode.getValue() != 5) { + me.setMode(5); # alt + } + } + } + }, + switchADIRS: func(newADIRS) { + if (newADIRS < 1 or newADIRS > 3) { + return; + } + me.activeADIRS = newADIRS; + }, + modeSwitch: func(newMode) { + me.mode = newMode; + }, + setCode: func(newCode) { + me.code = newCode; + forLoopFlag = 1; + for (index = 0; index < 4; index = index + 1) { + me.codeDigitsNodes[3 - index].setValue(substr(me.code, index, 1)); + } + forLoopFlag = 0; + }, + setMode: func(m) { + me.knobNode.setValue(m); + guiNode.setValue(guiModes[m]); + }, + fail: func() { + me.failed = 1; + me.serviceableNode.setBoolValue(0); + transponderPanel.atcFailLight(1); + }, + restore: func() { + me.failed = 0; + me.serviceableNode.setBoolValue(1); + transponderPanel.atcFailLight(0); + }, + ident: func() { + me.identNode.setValue(0); + settimer(func() { + me.identNode.setValue(1); + }, 0.1); + }, +}; + +var transponderPanel = { + atcSel: 1, + modeSel: 1, + identBtn: 0, + code: "2000", + codeDisp: "2000", + codeProp: props.globals.initNode("/systems/atc/transponder-code", "2000", "STRING"), + failLight: 0, + clearFlag: 0, + keypad: func(keyNum) { + if (props.globals.getNode("/controls/switches/annun-test", 1).getBoolValue() or props.globals.getNode("/systems/electrical/bus/dc-ess", 1).getValue() < 25) { + return; + } + if (keyNum < 0 or keyNum > 7) { + return; + } + + if (size(me.codeDisp) < 3) { + me.codeDisp = me.codeDisp ~ keyNum; + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + } elsif (size(me.codeDisp) == 3) { + me.codeDisp = me.codeDisp ~ keyNum; + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + me.code = me.codeDisp; + Transponders.vector[me.atcSel - 1].setCode(me.code); + } + }, + clearKey: func() { + if (props.globals.getNode("/controls/switches/annun-test", 1).getBoolValue() or props.globals.getNode("/systems/electrical/bus/dc-ess", 1).getValue() < 25) { + return; + } + if (me.codeDisp != "") { + if (me.clearFlag == 0) { + me.codeDisp = left(me.codeDisp, size(me.codeDisp) - 1); + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + me.clearFlag = 1; + } else { + me.codeDisp = ""; + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + } + } + }, + atcSwitch: func(newSel) { + if (newSel < 1 or newSel > 2) { + return; + } + me.atcSel = newSel; + + # update code + if (me.newSel = 1) { + Transponders.vector[1].selected = 0; + } else { + Transponders.vector[0].selected = 0; + } + + Transponders.vector[me.atcSel - 1].selected = 1; + me.code = Transponders.vector[me.atcSel - 1].code; + me.codeDisp = me.code; + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + Transponders.vector[me.atcSel - 1].setCode(me.code); # update transmitted code to other transponders code + me.clearFlag = 0; + + # update newly selected transponder + Transponders.vector[me.atcSel - 1].modeSwitch(me.modeSel); + me.atcFailLight(Transponders.vector[me.atcSel - 1].failed); + }, + modeSwitch: func(newMode) { + if (newMode < 0 or newMode > 5) { + return; + } + me.modeSel = newMode; + Transponders.vector[me.atcSel - 1].modeSwitch(me.modeSel); + }, + atcFailLight: func(newFail) { + if (newFail < 0 or newFail > 1) { + return; + } + me.failLight = newFail; + props.globals.getNode("/systems/atc/failed").setBoolValue(me.failLight); + }, + identSwitch: func() { + Transponders.vector[me.atcSel - 1].ident(); + }, + fastSetCode: func(newCode) { + if (size(newCode) != 4 or size(me.codeDisp) != 4) { + return; + } + me.clearFlag = 0; + me.code = newCode; + me.codeDisp = me.code; + me.codeProp.setValue(sprintf("%s", me.codeDisp)); + Transponders.vector[me.atcSel - 1].setCode(me.code); + } +}; + +var init = func() { + transponderPanel.atcSwitch(1); + transponderTimer.start(); +} + +# Handler for code change from generic dialog +setlistener("/instrumentation/transponder/id-code", func { + if (transponderPanel.code != idCode.getValue() and forLoopFlag == 0) { + transponderPanel.fastSetCode(sprintf("%04d", idCode.getValue())); + } +}, 0, 0); + +var Transponders = std.Vector.new([Transponder.new("/systems/electrical/bus/ac-ess-shed", 1), Transponder.new("/systems/electrical/bus/ac2", 2)]); + +var transponderTimer = maketimer(0.1, func() { + Transponders.vector[transponderPanel.atcSel - 1].update(); +}); diff --git a/Nasal/electrical.nas b/Nasal/electrical.nas index d5822579..d4ac2209 100644 --- a/Nasal/electrical.nas +++ b/Nasal/electrical.nas @@ -731,7 +731,6 @@ var ELEC = { setprop("/systems/electrical/outputs/stobe-lights", 0); setprop("/systems/electrical/outputs/tacan", 0); setprop("/systems/electrical/outputs/taxi-lights", 0); - setprop("/systems/electrical/outputs/transponder", 0); setprop("/systems/electrical/outputs/turn-coordinator", 0); setprop("/controls/lighting/fcu-panel-norm", 0); setprop("/controls/lighting/main-panel-norm", 0); @@ -767,7 +766,6 @@ var ELEC = { setprop("/systems/electrical/outputs/stobe-lights", dc_volt_std); setprop("/systems/electrical/outputs/tacan", dc_volt_std); setprop("/systems/electrical/outputs/taxi-lights", dc_volt_std); - setprop("/systems/electrical/outputs/transponder", dc_volt_std); setprop("/systems/electrical/outputs/turn-coordinator", dc_volt_std); setprop("/controls/lighting/fcu-panel-norm", getprop("/controls/lighting/fcu-panel-knb")); setprop("/controls/lighting/main-panel-norm", getprop("/controls/lighting/main-panel-knb")); diff --git a/Nasal/libraries.nas b/Nasal/libraries.nas index 8ff64be3..fa0c8867 100644 --- a/Nasal/libraries.nas +++ b/Nasal/libraries.nas @@ -205,6 +205,7 @@ var systemsInit = func { rmp.init(); acp.init(); ecam.ECAM_controller.init(); + atc.init(); } setlistener("/sim/signals/fdm-initialized", func { diff --git a/Systems/instrumentation.xml b/Systems/instrumentation.xml index e17382e3..d03bea03 100644 --- a/Systems/instrumentation.xml +++ b/Systems/instrumentation.xml @@ -29,6 +29,8 @@ /systems/static/pressure-inhg 0 0 + 1 + 1 @@ -134,7 +136,9 @@ transponder 0 + 2 /instrumentation/encoder/mode-c-alt-ft + /instrumentation/encoder/mode-s-alt-ft @@ -156,6 +160,11 @@ tcas 0 +