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
This commit is contained in:
Jonathan Redpath 2019-05-29 17:31:25 +01:00 committed by GitHub
parent 846005a217
commit 1db48daccb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 612 additions and 4 deletions

View file

@ -568,6 +568,10 @@
<onbat type="bool">false</onbat>
<skip type="bool">0</skip>
</adirs>
<atc>
<system-knob type="int">0</system-knob>
<mode-knob type="int">0</mode-knob>
</atc>
<APU>
<fire-btn type="bool">0</fire-btn>
<fire-btn-cover type="bool">0</fire-btn-cover>
@ -767,6 +771,10 @@
<acconfig n="0">
<autoconfig-running>0</autoconfig-running>
</acconfig>
<atc>
<transponder-code type="string">2000</transponder-code>
<failed type="bool">0</failed>
</atc>
<electrical n="0">
<bus n="0">
<dc-ess>0</dc-ess>
@ -972,7 +980,7 @@
<tcas><!-- http://wiki.flightgear.org/index.php/TCAS -->
<serviceable type="bool">true</serviceable><!-- TCAS ENABLE -->
<inputs>
<mode type="int">3</mode><!-- 0=off, 1=standby, 2=TA-only, 3=auto(TA/RA) -->
<mode type="int">1</mode><!-- 0=off, 1=standby, 2=TA-only, 3=auto(TA/RA) -->
</inputs>
<voice>
<file-prefix type="string">Sounds/tcas/female/</file-prefix>
@ -1563,6 +1571,9 @@
<acp>
<file>Aircraft/IDG-A32X/Nasal/acp.nas</file>
</acp>
<atc>
<file>Aircraft/IDG-A32X/Nasal/atc.nas</file>
</atc>
</nasal>
</PropertyList>

View file

@ -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);

View file

@ -350,6 +350,8 @@
<object-name>arpt_led</object-name>
<object-name>arpt_led.001</object-name>
<object-name>a-thr_led</object-name>
<object-name>atc-code</object-name>
<object-name>atc-test</object-name>
<object-name>audio_att_led</object-name>
<object-name>audio_att_sgn</object-name>
<object-name>audio_call_hf2_led</object-name>
@ -443,11 +445,25 @@
</condition>
</animation>
<animation>
<type>select</type>
<object-name>atc-code</object-name>
<condition>
<not>
<equals>
<property>controls/switches/annun-test</property>
<value>1</value>
</equals>
</not>
</condition>
</animation>
<!-- Not Yet Implemented Lights -->
<!-- Remove from this animation once you simulate -->
<animation>
<type>select</type>
<object-name>alt-text-test</object-name>
<object-name>atc-test</object-name>
<object-name>audio_att_sgn</object-name>
<object-name>audio_call_hf2_led</object-name>
<object-name>audio_call_hf1_led</object-name>
@ -5912,6 +5928,8 @@
<object-name>hdg-text-test</object-name>
<object-name>alt-text-test</object-name>
<object-name>vs-text-test</object-name>
<object-name>atc-code</object-name>
<object-name>atc-test</object-name>
<object-name>fpa-text</object-name>
<object-name>qnh-inhg</object-name>
<object-name>qnh-hpa</object-name>

View file

@ -9,7 +9,23 @@
<animation>
<name>Panel lighting</name>
<type>material</type>
<object-name>atc_0</object-name>
<object-name>atc_1</object-name>
<object-name>atc_2</object-name>
<object-name>atc_3</object-name>
<object-name>atc_4</object-name>
<object-name>atc_5</object-name>
<object-name>atc_6</object-name>
<object-name>atc_7</object-name>
<object-name>atc_abv</object-name>
<object-name>atc_body</object-name>
<object-name>atc_clr</object-name>
<object-name>atc_fail</object-name>
<object-name>atc_ident</object-name>
<object-name>atc_screen</object-name>
<object-name>atc_stby</object-name>
<object-name>atc_sys</object-name>
<object-name>atc_thrt</object-name>
<object-name>ecam_body</object-name>
<object-name>ecam_switch_body</object-name>
<object-name>engine_body</object-name>
@ -79,7 +95,6 @@
<object-name>radar_glare</object-name>
</effect>
<effect>
<inherits-from>Aircraft/IDG-A32X/Models/Effects/cockpit-irradiance</inherits-from>
<object-name>ecam_body</object-name>
@ -106,4 +121,309 @@
<object-name>vu112_aids</object-name>
<object-name>vu112_dfdr</object-name>
</effect>
<effect>
<inherits-from>Aircraft/IDG-A32X/Models/Effects/cockpit-irradiance</inherits-from>
<object-name>atc_0</object-name>
<object-name>atc_1</object-name>
<object-name>atc_2</object-name>
<object-name>atc_3</object-name>
<object-name>atc_4</object-name>
<object-name>atc_5</object-name>
<object-name>atc_6</object-name>
<object-name>atc_7</object-name>
<object-name>atc_abv</object-name>
<object-name>atc_body</object-name>
<object-name>atc_clr</object-name>
<object-name>atc_fail</object-name>
<object-name>atc_ident</object-name>
<object-name>atc_screen</object-name>
<object-name>atc_stby</object-name>
<object-name>atc_sys</object-name>
<object-name>atc_thrt</object-name>
</effect>
<text>
<name>atc-code</name>
<offsets>
<x-m>-0.01279</x-m>
<y-m>0.20</y-m>
<z-m>-0.13391</z-m>
<heading-deg>90</heading-deg>
</offsets>
<alignment>left-center</alignment>
<axis-alignment>xy-plane</axis-alignment>
<type type="string">text-value</type>
<property type="string">/systems/atc/transponder-code</property>
<format>%s</format>
<truncate type="bool">false</truncate>
<font type="string">led.txf</font>
<draw-text type="bool">true</draw-text>
<draw-alignment type="bool">false</draw-alignment>
<draw-boundingbox type="bool">false</draw-boundingbox>
<character-size>0.009</character-size>
<font-resolution>
<width type="int">32</width>
<height type="int">32</height>
</font-resolution>
</text>
<text>
<name>atc-test</name>
<offsets>
<x-m>-0.01279</x-m>
<y-m>0.20</y-m>
<z-m>-0.13391</z-m>
<heading-deg>90</heading-deg>
</offsets>
<alignment>left-center</alignment>
<axis-alignment>xy-plane</axis-alignment>
<type type="string">literal</type>
<text type="string">8888</text>
<font type="string">led.txf</font>
<draw-text type="bool">true</draw-text>
<draw-alignment type="bool">false</draw-alignment>
<draw-boundingbox type="bool">false</draw-boundingbox>
<character-size>0.009</character-size>
<font-resolution>
<width type="int">32</width>
<height type="int">32</height>
</font-resolution>
</text>
<animation>
<type>pick</type>
<object-name>atc_0</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(0);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_1</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(1);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_2</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(2);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_3</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(3);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_4</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(4);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_5</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(5);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_6</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(6);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_7</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.keypad(7);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_clr</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.clearKey();</script>
</binding>
</action>
</animation>
<animation>
<type>rotate</type>
<object-name>atc_sys</object-name>
<factor>-30</factor>
<offset-deg>30</offset-deg>
<center>
<x-m>-0.003352</x-m>
<y-m>0.131446</y-m>
<z-m>-0.13275</z-m>
</center>
<axis>
<x>0</x>
<y>0</y>
<z>1</z>
</axis>
<property>controls/atc/system-knob</property>
</animation>
<animation>
<type>pick</type>
<object-name>atc_sys</object-name>
<action>
<button>0</button>
<binding>
<command>property-cycle</command>
<property>controls/atc/system-knob</property>
<value>0</value>
<value>1</value>
</binding>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.atcSwitch(getprop("/controls/atc/system-knob") + 1);</script>
</binding>
</action>
</animation>
<animation>
<type>rotate</type>
<object-name>atc_stby</object-name>
<factor>-35</factor>
<offset-deg>70</offset-deg>
<center>
<x-m>0.01146</x-m>
<y-m>0.213663</y-m>
<z-m>-0.13086</z-m>
</center>
<axis>
<x>0</x>
<y>0</y>
<z>1</z>
</axis>
<property>controls/atc/mode-knob</property>
</animation>
<animation>
<type>pick</type>
<object-name>atc_stby</object-name>
<action>
<button>0</button>
<button>3</button>
<binding>
<command>property-cycle</command>
<property>controls/atc/mode-knob</property>
<value>0</value>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</binding>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.modeSwitch(getprop("/controls/atc/mode-knob") + 1);</script>
</binding>
</action>
<action>
<button>1</button>
<button>4</button>
<binding>
<command>property-cycle</command>
<property>controls/atc/mode-knob</property>
<value>4</value>
<value>3</value>
<value>2</value>
<value>1</value>
<value>0</value>
</binding>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.modeSwitch(getprop("/controls/atc/mode-knob") - 1);</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>atc_ident</object-name>
<action>
<button>0</button>
<binding>
<command>nasal</command>
<script>atc.transponderPanel.identSwitch();</script>
</binding>
</action>
</animation>
<animation>
<type>select</type>
<object-name>atc_fail</object-name>
<condition>
<and>
<property>systems/atc/failed</property>
<greater-than>
<property>systems/electrical/bus/dc-ess</property>
<value>25</value>
</greater-than>
</and>
</condition>
</animation>
</PropertyList>

245
Nasal/atc.nas Normal file
View file

@ -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();
});

View file

@ -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"));

View file

@ -205,6 +205,7 @@ var systemsInit = func {
rmp.init();
acp.init();
ecam.ECAM_controller.init();
atc.init();
}
setlistener("/sim/signals/fdm-initialized", func {

View file

@ -29,6 +29,8 @@
<static-pressure>/systems/static/pressure-inhg</static-pressure>
<quantum>0</quantum>
<tau>0</tau>
<encode-mode-c>1</encode-mode-c>
<encode-mode-s>1</encode-mode-s>
</altimeter>
<attitude-indicator>
@ -134,7 +136,9 @@
<transponder>
<name>transponder</name>
<number>0</number>
<mode>2</mode>
<mode-c-altitude>/instrumentation/encoder/mode-c-alt-ft</mode-c-altitude>
<mode-s-altitude>/instrumentation/encoder/mode-s-alt-ft</mode-s-altitude>
</transponder>
<turn-indicator>
@ -156,6 +160,11 @@
<tcas>
<name>tcas</name>
<number>0</number>
<!--<vertical-range>9900</vertical-range>
<lateral-range>30</lateral-range>
<intruder-use-self-alt>1</intruder-use-self-alt>
<intruder-inhb-alt>380</intruder-inhb-alt>
<intruder-self-alt>1700</intruder-self-alt> uncomment for 2019.3 -->
</tcas>
<radar>