diff --git a/A320-main.xml b/A320-main.xml
index 615cdfbd..8bad283f 100644
--- a/A320-main.xml
+++ b/A320-main.xml
@@ -479,6 +479,15 @@
1
+ -
+
+
+ nasal
+
+
+
@@ -4403,6 +4412,9 @@
Aircraft/A320-family/Nasal/Displays/CanvasQNH.nas
+
+ Aircraft/A320-family/Nasal/QRH/QRH.nas
+
Aircraft/A320-family/Nasal/FMGC/mcdu-messages.nas
diff --git a/Models/FlightDeck/QRH/1.jpeg b/Models/FlightDeck/QRH/1.jpeg
new file mode 100644
index 00000000..4672b2f1
Binary files /dev/null and b/Models/FlightDeck/QRH/1.jpeg differ
diff --git a/Models/FlightDeck/QRH/2.jpeg b/Models/FlightDeck/QRH/2.jpeg
new file mode 100644
index 00000000..9db337cd
Binary files /dev/null and b/Models/FlightDeck/QRH/2.jpeg differ
diff --git a/Models/FlightDeck/QRH/3.jpeg b/Models/FlightDeck/QRH/3.jpeg
new file mode 100644
index 00000000..ac0aa4ec
Binary files /dev/null and b/Models/FlightDeck/QRH/3.jpeg differ
diff --git a/Models/Instruments/PFD/PFD.nas b/Models/Instruments/PFD/PFD.nas
index a03262a9..a637ebdf 100644
--- a/Models/Instruments/PFD/PFD.nas
+++ b/Models/Instruments/PFD/PFD.nas
@@ -15,6 +15,8 @@ var updateR = 0;
var et = 0;
var altTens = 0;
var altPolarity = "";
+var track_diff = 0;
+var AICenter = nil;
# Fetch nodes:
var state1 = props.globals.getNode("/systems/thrust/state1", 1);
@@ -126,6 +128,16 @@ var inner_marker = props.globals.getNode("/instrumentation/marker-beacon/inner",
var flap_config = props.globals.getNode("/controls/flight/flaps-input", 1);
var hundredAbove = props.globals.getNode("/instrumentation/pfd/hundred-above", 1);
var minimum = props.globals.getNode("/instrumentation/pfd/minimums", 1);
+var aoa_1 = props.globals.getNode("/systems/navigation/adr/output/aoa-1", 1);
+var aoa_2 = props.globals.getNode("/systems/navigation/adr/output/aoa-2", 1);
+var aoa_3 = props.globals.getNode("/systems/navigation/adr/output/aoa-3", 1);
+var adr_1_switch = props.globals.getNode("/controls/navigation/adirscp/switches/adr-1", 1);
+var adr_2_switch = props.globals.getNode("/controls/navigation/adirscp/switches/adr-2", 1);
+var adr_3_switch = props.globals.getNode("/controls/navigation/adirscp/switches/adr-3", 1);
+var adr_1_fault = props.globals.getNode("/controls/navigation/adirscp/lights/adr-1-fault", 1);
+var adr_2_fault = props.globals.getNode("/controls/navigation/adirscp/lights/adr-2-fault", 1);
+var adr_3_fault = props.globals.getNode("/controls/navigation/adirscp/lights/adr-3-fault", 1);
+var air_data_switch = props.globals.getNode("/controls/navigation/switching/air-data", 1);
# Create Nodes:
var alt_diff = props.globals.initNode("/instrumentation/pfd/alt-diff", 0.0, "DOUBLE");
@@ -137,7 +149,7 @@ var horizon_ground = props.globals.initNode("/instrumentation/pfd/horizon-ground
var hdg_diff = props.globals.initNode("/instrumentation/pfd/hdg-diff", 0.0, "DOUBLE");
var hdg_scale = props.globals.initNode("/instrumentation/pfd/heading-scale", 0.0, "DOUBLE");
var track = props.globals.initNode("/instrumentation/pfd/track-deg", 0.0, "DOUBLE");
-var track_diff = props.globals.initNode("/instrumentation/pfd/track-hdg-diff", 0.0, "DOUBLE");
+#var track_diff = props.globals.initNode("/instrumentation/pfd/track-hdg-diff", 0.0, "DOUBLE"); # returns incorrect value
var du1_test = props.globals.initNode("/instrumentation/du/du1-test", 0, "BOOL");
var du1_test_time = props.globals.initNode("/instrumentation/du/du1-test-time", 0.0, "DOUBLE");
var du1_offtime = props.globals.initNode("/instrumentation/du/du1-off-time", 0.0, "DOUBLE");
@@ -200,6 +212,9 @@ var canvas_PFD_base = {
me.AI_horizon_hdg_trans = me["AI_heading"].createTransform();
me.AI_horizon_hdg_rot = me["AI_heading"].createTransform();
+ me.AI_fpv_trans = me["FPV"].createTransform();
+ me.AI_fpv_rot = me["FPV"].createTransform();
+
me.page = canvas_group;
return me;
@@ -212,7 +227,7 @@ var canvas_PFD_base = {
"AI_agl_g","AI_agl","AI_error","AI_group","FD_roll","FD_pitch","ALT_box_flash","ALT_box","ALT_box_amber","ALT_scale","ALT_target","ALT_target_digit","ALT_one","ALT_two","ALT_three","ALT_four","ALT_five","ALT_digits","ALT_tens","ALT_digit_UP",
"ALT_digit_DN","ALT_error","ALT_group","ALT_group2","ALT_frame","VS_pointer","VS_box","VS_digit","VS_error","VS_group","QNH","QNH_setting","QNH_std","QNH_box","LOC_pointer","LOC_scale","GS_scale","GS_pointer","CRS_pointer","HDG_target","HDG_scale",
"HDG_one","HDG_two","HDG_three","HDG_four","HDG_five","HDG_six","HDG_seven","HDG_digit_L","HDG_digit_R","HDG_error","HDG_group","HDG_frame","TRK_pointer","machError","ilsError","ils_code","ils_freq","dme_dist","dme_dist_legend","ILS_HDG_R","ILS_HDG_L",
- "ILS_right","ILS_left","outerMarker","middleMarker","innerMarker","v1_group","v1_text","vr_speed","F_target","S_target","FS_targets","flap_max","clean_speed","ground","ground_ref","spdLimError"];
+ "ILS_right","ILS_left","outerMarker","middleMarker","innerMarker","v1_group","v1_text","vr_speed","F_target","S_target","FS_targets","flap_max","clean_speed","ground","ground_ref","FPV","spdLimError"];
},
updateDu1: func() {
var elapsedtime_act = elapsedtime.getValue();
@@ -961,12 +976,15 @@ var canvas_PFD_base = {
me["HDG_target"].hide();
}
- me["TRK_pointer"].setTranslation((math.clamp(track_diff.getValue(), -23.62, 23.62) / 10) * 98.5416, 0);
+
+ var heading_deg = heading.getValue();
+ track_diff = geo.normdeg180(track.getValue() - heading_deg);
+ me["TRK_pointer"].setTranslation(me.getTrackDiffPixels(track_diff),0);
split_ils = split("/", ils_data1.getValue());
if (ap_ils_mode.getValue() == 1 and size(split_ils) == 2) {
magnetic_hdg = ils_crs.getValue();
- magnetic_hdg_dif = geo.normdeg180(magnetic_hdg - heading.getValue());
+ magnetic_hdg_dif = geo.normdeg180(magnetic_hdg - heading_deg);
if (magnetic_hdg_dif >= -23.62 and magnetic_hdg_dif <= 23.62) {
me["CRS_pointer"].setTranslation((magnetic_hdg_dif / 10) * 98.5416, 0);
me["ILS_HDG_R"].hide();
@@ -1010,6 +1028,28 @@ var canvas_PFD_base = {
me.AI_horizon_hdg_rot.setRotation(-roll_cur * D2R, me["AI_center"].getCenter());
me["AI_heading"].update();
},
+
+ # Get Angle of Attack from ADR1 or, depending on Switching panel, ADR3
+ getAOAForPFD1: func() {
+ if (air_data_switch.getValue() != -1 and adr_1_switch.getValue() and !adr_1_fault.getValue()) return aoa_1.getValue();
+ if (air_data_switch.getValue() == -1 and adr_3_switch.getValue() and !adr_3_fault.getValue()) return aoa_3.getValue();
+ return nil;
+ },
+
+ # Get Angle of Attack from ADR2 or, depending on Switching panel, ADR3
+ getAOAForPFD2: func() {
+ if (air_data_switch.getValue() != 1 and adr_2_switch.getValue() and !adr_2_fault.getValue()) return aoa_2.getValue();
+ if (air_data_switch.getValue() == 1 and adr_3_switch.getValue() and !adr_3_fault.getValue()) return aoa_3.getValue();
+ return nil;
+ },
+
+ # Convert difference between magnetic heading and track measured in degrees to pixel for display on PFDs
+ # And set max and minimum values
+ getTrackDiffPixels: func(track_diff_deg) {
+ return ((math.clamp(track_diff_deg, -23.62, 23.62) / 10) * 98.5416);
+ },
+
+
};
var canvas_PFD_1 = {
@@ -1087,6 +1127,26 @@ var canvas_PFD_1 = {
me["FD_pitch"].hide();
}
+ # If TRK FPA selected, display FPV on PFD1
+ if (ap_trk_sw.getValue() == 0 ) {
+ me["FPV"].hide();
+ } else {
+ var aoa = me.getAOAForPFD1();
+ if (aoa == nil or (systems.ADIRS.ADIRunits[0].aligned != 1 and att_switch.getValue() == 0) or (systems.ADIRS.ADIRunits[2].aligned != 1 and att_switch.getValue() == -1)){
+ me["FPV"].hide();
+ } else {
+ var roll_deg = roll.getValue() or 0;
+ AICenter = me["AI_center"].getCenter();
+ var track_x_translation = me.getTrackDiffPixels(track_diff);
+
+ me.AI_fpv_trans.setTranslation(track_x_translation, math.clamp(aoa, -20, 20) * 12.5);
+ me.AI_fpv_rot.setRotation(-roll_deg * D2R, AICenter);
+ me["FPV"].setRotation(roll_deg * D2R); # It shouldn't be rotated, only the axis should be
+ me["FPV"].show();
+ }
+
+ }
+
# ILS
if (ap_ils_mode.getValue() == 1) {
me["LOC_scale"].show();
@@ -1842,6 +1902,25 @@ var canvas_PFD_2 = {
me["FD_pitch"].hide();
}
+ # If TRK FPA selected, display FPV on PFD2
+ if (ap_trk_sw.getValue() == 0 ) {
+ me["FPV"].hide();
+ } else {
+ var aoa = me.getAOAForPFD2();
+ if (aoa == nil or (systems.ADIRS.ADIRunits[1].aligned != 1 and att_switch.getValue() == 0) or (systems.ADIRS.ADIRunits[2].aligned != 1 and att_switch.getValue() == 1)) {
+ me["FPV"].hide();
+ } else {
+ var roll_deg = roll.getValue() or 0;
+ AICenter = me["AI_center"].getCenter();
+ var track_x_translation = me.getTrackDiffPixels(track_diff);
+
+ me.AI_fpv_trans.setTranslation(track_x_translation, math.clamp(aoa, -20, 20) * 12.5);
+ me.AI_fpv_rot.setRotation(-roll_deg * D2R, AICenter);
+ me["FPV"].setRotation(roll_deg * D2R); # It shouldn't be rotated, only the axis should be
+ me["FPV"].show();
+ }
+ }
+
# ILS
if (ap_ils_mode2.getValue() == 1) {
me["LOC_scale"].show();
diff --git a/Models/Instruments/PFD/res/pfd.svg b/Models/Instruments/PFD/res/pfd.svg
index 88060ede..9dcde382 100644
--- a/Models/Instruments/PFD/res/pfd.svg
+++ b/Models/Instruments/PFD/res/pfd.svg
@@ -8,7 +8,7 @@
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="pfd.svg"
- inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
id="svg2"
version="1.1"
viewBox="0 0 1024 1024"
@@ -39,15 +39,15 @@
showguides="true"
inkscape:current-layer="svg2"
inkscape:window-maximized="1"
- inkscape:window-y="-8"
- inkscape:window-x="-8"
- inkscape:cy="567.21927"
- inkscape:cx="992.76655"
- inkscape:zoom="1.0773413"
+ inkscape:window-y="18"
+ inkscape:window-x="3840"
+ inkscape:cy="557.03495"
+ inkscape:cx="619.57094"
+ inkscape:zoom="0.53867065"
showgrid="true"
id="namedview371"
- inkscape:window-height="705"
- inkscape:window-width="1366"
+ inkscape:window-height="1062"
+ inkscape:window-width="1920"
inkscape:pageshadow="2"
inkscape:pageopacity="1"
guidetolerance="10"
@@ -1396,9 +1396,10 @@
+ style="fill:none;fill-opacity:1;stroke:#c9d121;stroke-width:3.54375;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ inkscape:label="fixed_aircraft_outline_1" />
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:label="fixed_aircraft_outline_2" />
LIM
+
+
+
+
+
+
diff --git a/Nasal/QRH/QRH.nas b/Nasal/QRH/QRH.nas
new file mode 100644
index 00000000..73fc21df
--- /dev/null
+++ b/Nasal/QRH/QRH.nas
@@ -0,0 +1,94 @@
+# A3XX Canvas QRH
+# Jonathan Redpath (legoboyvdlp)
+
+# Copyright (c) 2020 Jonathan Redpath (legoboyvdlp)
+
+var QRHpageNo = props.globals.initNode("/canvas/canvasQRH/page-number", 1, "INT");
+
+var _pageNo = 1;
+var _MAXPAGE = 3;
+
+var width = 550;
+var height = 625;
+
+var QRH = nil;
+
+var prevPage = func() {
+ _pageNo = QRHpageNo.getValue();
+ if (_pageNo == 1) { return; }
+ QRHpageNo.setValue(_pageNo - 1);
+};
+
+var nextPage = func() {
+ _pageNo = QRHpageNo.getValue();
+ if (_pageNo == _MAXPAGE) { return; }
+ QRHpageNo.setValue(_pageNo + 1);
+};
+
+
+var createCanvasQRH = func() {
+ var window = canvas.Window.new([width,height],"dialog")
+ .set("title","A320 QRH");
+
+ var qrhCanvas = window.createCanvas().set("background", canvas.style.getColor("bg_color"));
+ var root = qrhCanvas.createGroup();
+
+ var myHBox = canvas.HBoxLayout.new();
+ qrhCanvas.setLayout(myHBox);
+
+ QRH = canvas.gui.widgets.Label.new(root, canvas.style, {} )
+ .setImage("Aircraft/A320-family/Models/FlightDeck/QRH/" ~ QRHpageNo.getValue() ~ ".jpeg")
+ .move(0,-25)
+ .setSize(400,625);
+ myHBox.addItem(QRH);
+
+ var verticalGroup = canvas.VBoxLayout.new();
+ myHBox.addItem(verticalGroup);
+
+ var buttonInc = canvas.gui.widgets.Button.new(root, canvas.style, {})
+ .setText("Size Up")
+ .setFixedSize(75,25);
+ var buttonReset = canvas.gui.widgets.Button.new(root, canvas.style, {})
+ .setText("Reset Size")
+ .setFixedSize(75,25);
+ var buttonDec = canvas.gui.widgets.Button.new(root, canvas.style, {})
+ .setText("Size Down")
+ .setFixedSize(75,25);
+ var buttonPrev = canvas.gui.widgets.Button.new(root, canvas.style, {})
+ .setText("Prev Page")
+ .setFixedSize(75,25);
+ var buttonNext = canvas.gui.widgets.Button.new(root, canvas.style, {})
+ .setText("Next Page")
+ .setFixedSize(75,25);
+
+ buttonInc.listen("clicked", func {
+ width = width * 1.10;
+ height = height * 1.10;
+ window.setSize(width, height);
+ });
+ buttonReset.listen("clicked", func {
+ width = 550;
+ height = 650;
+ window.setSize(width, height);
+ });
+ buttonDec.listen("clicked", func {
+ width = width * 0.91;
+ height = height * 0.91;
+ window.setSize(width, height);
+ });
+ buttonPrev.listen("clicked", func {
+ prevPage();
+ QRH.setImage("Aircraft/A320-family/Models/FlightDeck/QRH/" ~ QRHpageNo.getValue() ~ ".jpeg");
+ });
+ buttonNext.listen("clicked", func {
+ nextPage();
+ QRH.setImage("Aircraft/A320-family/Models/FlightDeck/QRH/" ~ QRHpageNo.getValue() ~ ".jpeg");
+ });
+
+
+ verticalGroup.addItem(buttonInc);
+ verticalGroup.addItem(buttonReset);
+ verticalGroup.addItem(buttonDec);
+ verticalGroup.addItem(buttonPrev);
+ verticalGroup.addItem(buttonNext);
+}
\ No newline at end of file
diff --git a/Systems/a320-electrical.xml b/Systems/a320-electrical.xml
index 3cd7cffb..8fb63914 100644
--- a/Systems/a320-electrical.xml
+++ b/Systems/a320-electrical.xml
@@ -1600,13 +1600,6 @@
-
-
-
- /systems/electrical/relay/dc-ess-shed-switch/contact-pos eq 1
-
-
-
@@ -1806,7 +1799,7 @@
/systems/electrical/bus/dc-ess
- 1
+ /systems/electrical/relay/dc-ess-shed-switch/contact-pos
diff --git a/Systems/a320-fuel.xml b/Systems/a320-fuel.xml
index d4afafd8..fa17b802 100644
--- a/Systems/a320-fuel.xml
+++ b/Systems/a320-fuel.xml
@@ -768,7 +768,9 @@
/consumables/fuel/tank[3]/level-norm lt 0.9999
-
+
+
+
/systems/fuel/internal/left-outer-wing-tank-refuel
-/systems/fuel/internal/left-wing-outer-to-inner-tank