From d05de526cad11bd355a662fe25c96bcc38e3a883 Mon Sep 17 00:00:00 2001
From: legoboyvdlp R <legoboyvdlp@gmail.com>
Date: Tue, 29 Oct 2019 15:19:43 +0000
Subject: [PATCH] FWC Phases

---
 A320-100-CFM.xml                      |   1 +
 A320-200-CFM.xml                      |   1 +
 A320-200-IAE.xml                      |   1 +
 A320-main.xml                         |   6 +-
 A320neo-CFM.xml                       |   1 +
 A320neo-PW.xml                        |   1 +
 AircraftConfig/acconfig.nas           |   5 +-
 Models/FlightDeck/a320.flightdeck.xml |  12 +-
 Nasal/ECAM.nas                        | 111 +-----------
 Nasal/ECAM/ECAM-controller.nas        |  27 ++-
 Nasal/ECAM/ECAM-logic.nas             | 191 ++++++++++++++++++++
 Nasal/ECAM/ECAM-messages.nas          |  21 +++
 Nasal/ECAM/ECAM-phases.nas            | 241 ++++++++++++++++++++++++++
 Nasal/FMGC.nas                        |   4 +-
 Nasal/fadec-common.nas                |   6 +-
 Nasal/libraries.nas                   |   8 +
 Nasal/property-tree-setup.nas         |  62 +++++++
 Systems/a320-fwc.xml                  |  31 ++++
 Systems/upper-ecam.xml                | 148 ++++++++++++++++
 revision.txt                          |   2 +-
 20 files changed, 764 insertions(+), 116 deletions(-)
 create mode 100644 Nasal/ECAM/ECAM-phases.nas
 create mode 100644 Nasal/property-tree-setup.nas
 create mode 100644 Systems/a320-fwc.xml

diff --git a/A320-100-CFM.xml b/A320-100-CFM.xml
index 414297a3..4b557e69 100644
--- a/A320-100-CFM.xml
+++ b/A320-100-CFM.xml
@@ -136,6 +136,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">
 	<system file="fuel"/>
 	<system file="glass-effect1"/>
 	<system file="a320-fcs"/>
+	<system file="a320-fwc"/>
 	<system file="a320-spoiler"/>
 	<system file="a320-electrical"/>
 	<system file="a320-hydraulic"/>
diff --git a/A320-200-CFM.xml b/A320-200-CFM.xml
index 75bd4d56..7a2c7d03 100644
--- a/A320-200-CFM.xml
+++ b/A320-200-CFM.xml
@@ -136,6 +136,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">
 	<system file="fuel"/>
 	<system file="glass-effect1"/>
 	<system file="a320-fcs"/>
+	<system file="a320-fwc"/>
 	<system file="a320-spoiler"/>
 	<system file="a320-electrical"/>
 	<system file="a320-hydraulic"/>
diff --git a/A320-200-IAE.xml b/A320-200-IAE.xml
index c0d51b1a..7de9fec7 100644
--- a/A320-200-IAE.xml
+++ b/A320-200-IAE.xml
@@ -136,6 +136,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">
 	<system file="fuel"/>
 	<system file="glass-effect1"/>
 	<system file="a320-fcs"/>
+	<system file="a320-fwc"/>
 	<system file="a320-spoiler"/>
 	<system file="a320-electrical"/>
 	<system file="a320-hydraulic"/>
diff --git a/A320-main.xml b/A320-main.xml
index f9b02812..e8c07a0d 100644
--- a/A320-main.xml
+++ b/A320-main.xml
@@ -1580,6 +1580,9 @@
 	</aircraft>
 	
 	<nasal>
+		<pts>
+			<file>Aircraft/A320-family/Nasal/property-tree-setup.nas</file>
+		</pts>
 		<libraries>
 			<file>Aircraft/A320-family/Nasal/libraries.nas</file>
 			<file>Aircraft/A320-family/Nasal/buttons.nas</file>
@@ -1611,7 +1614,7 @@
 			<file>Aircraft/A320-family/Nasal/it-fbw.nas</file>
 		</fbw>
 		<fcu>
-			<file>Aircraft/A320-family/Nasal/FMGC/fcu.nas</file>
+			<file>Aircraft/A320-family/Nasal/FMGC/FCU.nas</file>
 		</fcu>
 		<fmgc>
 			<file>Aircraft/A320-family/Nasal/FMGC.nas</file>
@@ -1650,6 +1653,7 @@
 			<file>Aircraft/A320-family/Nasal/ECAM/ECAM-controller.nas</file>
 			<file>Aircraft/A320-family/Nasal/ECAM/ECAM-logic.nas</file>
 			<file>Aircraft/A320-family/Nasal/ECAM/ECAM-messages.nas</file>
+			<file>Aircraft/A320-family/Nasal/ECAM/ECAM-phases.nas</file>
 		</ecam>
 		<icing>
 			<file>Aircraft/A320-family/Nasal/icing.nas</file>
diff --git a/A320neo-CFM.xml b/A320neo-CFM.xml
index 9c5b6724..a86f4889 100644
--- a/A320neo-CFM.xml
+++ b/A320neo-CFM.xml
@@ -136,6 +136,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">
 	<system file="fuel"/>
 	<system file="glass-effect1"/>
 	<system file="a320-fcs"/>
+	<system file="a320-fwc"/>
 	<system file="a320-spoiler"/>
 	<system file="a320-electrical"/>
 	<system file="a320-hydraulic"/>
diff --git a/A320neo-PW.xml b/A320neo-PW.xml
index 39a8e469..b84e5c0d 100644
--- a/A320neo-PW.xml
+++ b/A320neo-PW.xml
@@ -136,6 +136,7 @@ xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">
 	<system file="fuel"/>
 	<system file="glass-effect1"/>
 	<system file="a320-fcs"/>
+	<system file="a320-fwc"/>
 	<system file="a320-spoiler"/>
 	<system file="a320-electrical"/>
 	<system file="a320-hydraulic"/>
diff --git a/AircraftConfig/acconfig.nas b/AircraftConfig/acconfig.nas
index 12471b0a..45ebd411 100644
--- a/AircraftConfig/acconfig.nas
+++ b/AircraftConfig/acconfig.nas
@@ -506,7 +506,10 @@ var takeoff = func {
 				libraries.flaptimer.start();
 				setprop("/controls/flight/elevator-trim", -0.07);
 				systems.arm_autobrake(3);
-				libraries.ECAM.toConfig();
+				setprop("/ECAM/to-config-test", 1);
+				settimer(func {
+					setprop("/ECAM/to-config-test", 0);
+				}, 1);
 			}
 		});
 	}
diff --git a/Models/FlightDeck/a320.flightdeck.xml b/Models/FlightDeck/a320.flightdeck.xml
index 31c7a060..85a1d6d4 100644
--- a/Models/FlightDeck/a320.flightdeck.xml
+++ b/Models/FlightDeck/a320.flightdeck.xml
@@ -1436,9 +1436,17 @@
 						<value>25</value>
 					</greater-than-equals>
 				</condition>
-				<command>nasal</command>
-				<script>libraries.ECAM.toConfig();</script>
+				<command>property-assign</command>
+				<property>/ECAM/to-config-test</property>
+				<value>1</value>
 			</binding>
+			<mod-up>
+				<binding>
+					<command>property-assign</command>
+					<property>/ECAM/to-config-test</property>
+					<value>0</value>
+				</binding>
+			</mod-up>
 		</action>
 	</animation>
 
diff --git a/Nasal/ECAM.nas b/Nasal/ECAM.nas
index ef2bce9d..3f12bafb 100644
--- a/Nasal/ECAM.nas
+++ b/Nasal/ECAM.nas
@@ -52,9 +52,6 @@ var ECAM = {
 	init: func() {
 		setprop("/ECAM/engine-start-time", 0);
 		setprop("/ECAM/engine-start-time-switch", 0);
-		setprop("/ECAM/to-memo-enable", 1);
-		setprop("/ECAM/to-config", 0);
-		setprop("/ECAM/ldg-memo-enable", 0);
 		setprop("/systems/gear/landing-gear-warning-light", 0);
 		setprop("/ECAM/Lower/page", "door");
 		setprop("/ECAM/Lower/man-select", 0);
@@ -132,7 +129,12 @@ var ECAM = {
 		wow = getprop("/gear/gear[0]/wow");
 		eng = getprop("/options/eng");
 		
-		if (stateL == 3 and stateR == 3 and wow == 1) {
+		if (stateL != 3 or stateR != 3) {
+			if (getprop("/ECAM/engine-start-time-switch") != 0) {
+				setprop("/ECAM/engine-start-time-switch", 0);
+				setprop("/ECAM/engine-start-time", 0);
+			}
+		} else if (stateL == 3 and stateR == 3 and wow == 1) {
 			if (getprop("/ECAM/engine-start-time-switch") != 1) {
 				setprop("/ECAM/engine-start-time", getprop("/sim/time/elapsed-sec"));
 				setprop("/ECAM/engine-start-time-switch", 1);
@@ -143,26 +145,8 @@ var ECAM = {
 			}
 		}
 		
-		if (getprop("/ECAM/warning-phase") >= 3) {
-			setprop("/ECAM/to-memo-enable", 0);
-		} else {
-			setprop("/ECAM/to-memo-enable", 1);
-		}
-		
-		if (getprop("/position/gear-agl-ft") <= 2000 and (getprop("/FMGC/status/phase") == 3 or getprop("/FMGC/status/phase") == 4 or getprop("/FMGC/status/phase") == 5) and wow == 0) {
-			setprop("/ECAM/ldg-memo-enable", 1);
-		} else if (getprop("/ECAM/left-msg") == "LDG-MEMO" and speed <= 80 and wow == 1) {
-			setprop("/ECAM/ldg-memo-enable", 0);
-		} else if (getprop("/ECAM/left-msg") != "LDG-MEMO") {
-			setprop("/ECAM/ldg-memo-enable", 0);
-		}
-		
-		if (stateL == 3 and stateR == 3 and getprop("/ECAM/engine-start-time") + 120 < getprop("/sim/time/elapsed-sec") and getprop("/ECAM/to-memo-enable") == 1 and wow == 1) {
-			setprop("/ECAM/left-msg", "TO-MEMO");
-		} elsif (getprop("/ECAM/ldg-memo-enable") == 1) {
-			setprop("/ECAM/left-msg", "LDG-MEMO");
-		} elsif (getprop("/ECAM/show-left-msg") == 1) {
-			setprop("/ECAM/left-msg", "MSG"); # messages should have priority over memos - how?
+		if (getprop("/ECAM/show-left-msg") == 1) {
+			setprop("/ECAM/left-msg", "MSG");
 		} else {
 			setprop("/ECAM/left-msg", "NONE");
 		}
@@ -173,29 +157,6 @@ var ECAM = {
 			setprop("/ECAM/right-msg", "NONE");
 		}
 		
-		if (getprop("/controls/autobrake/mode") == 3 and getprop("/controls/lighting/no-smoking-sign") == 1 and getprop("/controls/lighting/seatbelt-sign") == 1 and getprop("/controls/flight/speedbrake-arm") == 1 and getprop("/controls/flight/flap-pos") > 0 
-		and getprop("/controls/flight/flap-pos") < 5) {
-			# Do nothing
-		} else {
-			setprop("/ECAM/to-config", 0);
-		}
-		
-		if (eng == "IAE") {
-			eprlim = getprop("/controls/engines/epr-limit");
-			if (abs(getprop("/engines/engine[0]/epr-actual") - eprlim) <= 0.005 or abs(getprop("/engines/engine[0]/epr-actual") - eprlim) <= 0.005) {
-				toPowerSet = 1;
-			} else {
-				toPowerSet = 0;
-			}
-		} else {
-			n1lim = getprop("/controls/engines/n1-limit");
-			if (abs(getprop("/engines/engine[0]/n1-actual") - n1lim) <= 0.1 or abs(getprop("/engines/engine[0]/n1-actual") - n1lim) <= 0.1) {
-				toPowerSet = 1;
-			} else {
-				toPowerSet = 0;
-			}
-		}
-		
 		# AP / ATHR warnings
 		if (ap_active == 1 and getprop("/it-autoflight/output/ap-warning") == 0) {
 			ap_active = 0;
@@ -232,62 +193,8 @@ var ECAM = {
 			setprop("/it-autoflight/output/athr-warning", 0);
 		}
 		
-		
-		# Warning Phases
-		if (getprop("/systems/electrical/bus/ac-1") < 110 and getprop("/systems/electrical/bus/ac-2") < 110 and getprop("/systems/electrical/bus/ac-ess") < 110) { # Reset warning phases
-			if (getprop("/ECAM/warning-phase") != 1) {
-				setprop("/ECAM/warning-phase", 1);
-			}
-		} else {
-			phase = getprop("/ECAM/warning-phase");
-			mode = getprop("/modes/pfd/fma/pitch-mode");
-			modeI = getprop("/it-autoflight/mode/vert");
-			
-			if (phase == 1 and (stateL == 3 or stateR == 3)) {
-				setprop("/ECAM/warning-phase", 2);
-			} else if (phase == 2 and toPowerSet) {
-				setprop("/ECAM/warning-phase", 3);
-			} else if (phase == 3 and speed >= 80) {
-				setprop("/ECAM/warning-phase", 4);
-			} else if ((phase >= 2 and phase <= 4) and getprop("/fdm/jsbsim/position/wow") == 0) { # Liftoff
-				setprop("/ECAM/warning-phase", 5);
-			} else if (phase == 5 and getprop("/position/gear-agl-ft") >= 1500) {
-				setprop("/ECAM/warning-phase", 6);
-			} else if (phase == 6 and getprop("/position/gear-agl-ft") < 800) {
-				if (mode == "OP CLB" or mode == "CLB" or (modeI == "V/S" and getprop("/it-autoflight/input/vs") >= 100) or (modeI == "FPA" and getprop("/it-autoflight/input/fpa") >= 0.1)) {
-					# Do not do this if we are climbing, not in FCOM, but prevents terrain  from causing early mode change. If this ends up using baro alt, not radio, then delete this if
-				} else {
-					setprop("/ECAM/warning-phase", 7);
-				}
-			} else if (phase == 7 and getprop("/fdm/jsbsim/position/wow") == 1) { # Touchdown
-				setprop("/ECAM/warning-phase", 8);
-			} else if (phase == 8 and speed < 80) {
-				setprop("/ECAM/warning-phase", 9);
-			} else if (phase == 9 and (stateL == 0 or stateR == 0)) {
-				setprop("/ECAM/warning-phase", 10);
-				setprop("/ECAM/warning-phase-10-time", getprop("/sim/time/elapsed-sec"));
-			} else if (phase == 10 and getprop("/ECAM/warning-phase-10-time") + 300 < getprop("/sim/time/elapsed-sec")) { # After 5 mins, reset to phase 1
-				setprop("/ECAM/warning-phase", 1);
-			}
-		}
-		
 		LowerECAM.loop();
 	},
-	toConfig: func() {
-		stateL = getprop("/engines/engine[0]/state");
-		stateR = getprop("/engines/engine[1]/state");
-		wow = getprop("/gear/gear[0]/wow");
-		
-		if ((getprop("/ECAM/warning-phase") == 2 or getprop("/ECAM/warning-phase") == 9) and wow == 1 and (stateL == 3 or stateR == 3) and getprop("/ECAM/left-msg") != "TO-MEMO") {
-			setprop("/ECAM/to-memo-enable", 1);
-			setprop("/ECAM/engine-start-time", getprop("/ECAM/engine-start-time") - 120);
-		}
-		
-		if (getprop("/controls/autobrake/mode") == 3 and getprop("/controls/switches/no-smoking-sign") == 1 and getprop("/controls/switches/seatbelt-sign") == 1 and getprop("/controls/flight/speedbrake-arm") == 1 and getprop("/controls/flight/flap-pos") > 0 
-		and getprop("/controls/flight/flap-pos") < 5) {
-			setprop("/ECAM/to-config", 1);
-		}
-	},
 };
 
 ECAM.MSGclr();
@@ -477,7 +384,7 @@ var LowerECAM = {
 				} else if (warnPhase == 6) {
 					flapLever = getprop("/controls/flight/flap-lever");
 					gearLever = getprop("/controls/gear/gear-down");
-					agl = getprop("/position/gear-agl-ft");
+					agl = pts.Position.gearAglFt.getValue();
 					
 					if (CRZCounting and (toPowerSet or flapLever > 0) and !CRZCondition) {
 						if (CRZTime + 60 < elapsedSec) {
diff --git a/Nasal/ECAM/ECAM-controller.nas b/Nasal/ECAM/ECAM-controller.nas
index 3a8735a1..648741ef 100644
--- a/Nasal/ECAM/ECAM-controller.nas
+++ b/Nasal/ECAM/ECAM-controller.nas
@@ -30,7 +30,7 @@ var hasCleared = 0;
 var statusFlag = 0;
 
 var warning = {
-	new: func(msg,colour = "g",aural = 9,light = 9,hasSubmsg = 0,lastSubmsg = 0, sdPage = "nil") {
+	new: func(msg,colour = "g",aural = 9,light = 9,hasSubmsg = 0,lastSubmsg = 0, sdPage = "nil", isMemo = 0) {
 		var t = {parents:[warning]};
 		
 		t.msg = msg;
@@ -44,6 +44,7 @@ var warning = {
 		t.noRepeat2 = 0;
 		t.clearFlag = 0;
 		t.sdPage = sdPage;
+		t.isMemo = isMemo;
 		t.hasCalled = 0;
 		
 		return t
@@ -150,12 +151,16 @@ var ECAM_controller = {
 		me.reset();
 	},
 	loop: func() {
-		# check active messages
 		if ((systems.ELEC.Bus.acEss.getValue() >= 110 or systems.ELEC.Bus.ac2.getValue() >= 110) and !getprop("/systems/acconfig/acconfig-running")) {
+			# update FWC phases
+			phaseLoop();
+			
+			# check active messages
 			messages_priority_3();
 			messages_priority_2();
 			messages_priority_1();
 			messages_priority_0();
+			messages_config_memo();
 			messages_memo();
 			messages_right_memo();
 		} else {
@@ -176,6 +181,8 @@ var ECAM_controller = {
 			rightLines[n].setValue("");
 		}
 		
+		if (getprop("/systems/acconfig/autoconfig-running")) { return; }
+		
 		# write to ECAM
 		var counter = 0;
 		
@@ -188,6 +195,12 @@ var ECAM_controller = {
 				counter += 1;
 			}
 		}
+			
+		if (lines[0].getValue() == "" and flash == 0) { # disable left memos if a warning exists. Warnings are processed first, so this stops leftmemos if line1 is not empty
+			foreach (var c; configmemos.vector) {
+				c.write();
+			}
+		}
 		
 		if (lines[0].getValue() == "" and flash == 0) { # disable left memos if a warning exists. Warnings are processed first, so this stops leftmemos if line1 is not empty
 			foreach (var l; leftmemos.vector) {
@@ -220,6 +233,12 @@ var ECAM_controller = {
 			}
 		}
 		
+		foreach (var l; configmemos.vector) {
+			if (l.active == 1) {
+				l.active = 0;
+			}
+		}
+		
 		foreach (var l; leftmemos.vector) {
 			if (l.active == 1) {
 				l.active = 0;
@@ -251,7 +270,7 @@ var ECAM_controller = {
 		if (leftOverflow.getBoolValue()) {
 			foreach (var w; warnings.vector) {
 				if (counter >= 8) { break; }
-				if (w.active == 1 and w.clearFlag != 1) {
+				if (w.active == 1 and w.clearFlag != 1 and w.isMemo != 1) {
 					counter += 1;
 					if (w.hasSubmsg == 1) { continue; }
 					w.clearFlag = 1;
@@ -261,7 +280,7 @@ var ECAM_controller = {
 			}
 		} else {
 			foreach (var w; warnings.vector) {
-				if (w.active == 1 and w.clearFlag != 1 and w.hasSubmsg == 1) {
+				if (w.active == 1 and w.clearFlag != 1 and w.hasSubmsg == 1 and w.isMemo != 1) {
 					w.clearFlag = 1;
 					hasCleared = 1;
 					statusFlag = 1;
diff --git a/Nasal/ECAM/ECAM-logic.nas b/Nasal/ECAM/ECAM-logic.nas
index 81b73057..3cc59780 100644
--- a/Nasal/ECAM/ECAM-logic.nas
+++ b/Nasal/ECAM/ECAM-logic.nas
@@ -23,10 +23,12 @@ var gear       = props.globals.getNode("/gear/gear-pos-norm", 1);
 var cutoff1    = props.globals.getNode("/controls/engines/engine[0]/cutoff-switch", 1);
 var cutoff2    = props.globals.getNode("/controls/engines/engine[1]/cutoff-switch", 1);
 var engOpt     = props.globals.getNode("/options/eng", 1);
+
 # local variables
 var phaseVar = nil;
 var dualFailFACActive = 1;
 var emerConfigFACActive = 1;
+var gear_agl_cur = nil;
 
 var messages_priority_3 = func {
 	phaseVar = phaseNode.getValue();
@@ -935,6 +937,30 @@ var messages_priority_2 = func {
 		ECAM_controller.warningReset(dcEmerconfigManOn);
 	}
 	
+	if (fcu.FCUController.FCU1.failed and fcu.FCUController.FCU2.failed and systems.ELEC.Bus.dcEss.getValue() >= 25 and systems.ELEC.Bus.dcEss.getValue() >= 25) {
+		fcuFault.active = 1;
+		fcuFaultBaro.active = 1;
+	} else {
+		ECAM_controller.warningReset(fcuFault);
+		ECAM_controller.warningReset(fcuFaultBaro);
+	}
+	
+	if (fcu.FCUController.FCU1.failed and !fcu.FCUController.FCU2.failed and systems.ELEC.Bus.dcEss.getValue() >= 25) {
+		fcuFault1.active = 1;
+		fcuFault1Baro.active = 1;
+	} else {
+		ECAM_controller.warningReset(fcuFault1);
+		ECAM_controller.warningReset(fcuFault1Baro);
+	}
+	
+	if (fcu.FCUController.FCU2.failed and !fcu.FCUController.FCU1.failed and systems.ELEC.Bus.dc2.getValue() >= 25) {
+		fcuFault2.active = 1;
+		fcuFault2Baro.active = 1;
+	} else {
+		ECAM_controller.warningReset(fcuFault2);
+		ECAM_controller.warningReset(fcuFault2Baro);
+	}
+	
 	# APU EMER SHUT DOWN
 	if (apuEmerShutdown.clearFlag == 0 and systems.apuEmerShutdown.getBoolValue() and !getprop("/systems/fire/apu/warning-active") and (getprop("/ECAM/warning-phase") == 6 or getprop("/ECAM/warning-phase") >= 9 or getprop("/ECAM/warning-phase") <= 2)) {
 		apuEmerShutdown.active = 1;
@@ -1020,6 +1046,171 @@ var messages_priority_2 = func {
 var messages_priority_1 = func {}
 var messages_priority_0 = func {}
 
+var messages_config_memo = func {
+	if (getprop("/controls/flight/flap-lever") == 0 or getprop("/controls/flight/flap-lever") == 4 or getprop("/controls/flight/speedbrake") != 0 or getprop("/fdm/jsbsim/hydraulics/elevator-trim/final-deg") > 1.75 or getprop("/fdm/jsbsim/hydraulics/elevator-trim/final-deg") < -3.65 or getprop("/fdm/jsbsim/hydraulics/rudder/trim-cmd-deg") < -3.55 or getprop("/fdm/jsbsim/hydraulics/rudder/trim-cmd-deg") > 3.55) {
+		setprop("/ECAM/to-config-normal", 0);
+	} else {
+		setprop("/ECAM/to-config-normal", 1);
+	}
+	
+	if (getprop("/ECAM/to-config-test") and (getprop("/ECAM/warning-phase") == 2 or getprop("/ECAM/warning-phase") == 9)) {
+		setprop("/ECAM/to-config-set", 1);
+	} else {
+		setprop("/ECAM/to-config-set", 0);
+	}
+	
+	if (!getprop("/ECAM/to-config-normal") or getprop("/ECAM/warning-phase") == 6) {
+		setprop("/ECAM/to-config-reset", 1);
+	} else {
+		setprop("/ECAM/to-config-reset", 0);
+	}
+	
+	if (getprop("/controls/autobrake/mode") == 3) {
+		toMemoLine1.msg = "T.O AUTO BRK MAX";
+		toMemoLine1.colour = "g";
+	} else {
+		toMemoLine1.msg = "T.O AUTO BRK.....MAX";
+		toMemoLine1.colour = "c";
+	}
+	
+	if (getprop("/controls/switches/seatbelt-sign") and getprop("/controls/switches/no-smoking-sign")) {
+		toMemoLine2.msg = "    SIGNS ON";
+		toMemoLine2.colour = "g";
+	} else {
+		toMemoLine2.msg = "    SIGNS.........ON";
+		toMemoLine2.colour = "c";
+	}
+	
+	if (getprop("/controls/flight/speedbrake-arm")) {
+		toMemoLine3.msg = "    SPLRS ARM";
+		toMemoLine3.colour = "g";
+	} else {
+		toMemoLine3.msg = "    SPLRS........ARM";
+		toMemoLine3.colour = "c";
+	}
+	
+	if (getprop("/controls/flight/flap-pos") > 0 and getprop("/controls/flight/flap-pos") < 5) {
+		toMemoLine4.msg = "    FLAPS T.O";
+		toMemoLine4.colour = "g";
+	} else {
+		toMemoLine4.msg = "    FLAPS........T.O";
+		toMemoLine4.colour = "c";
+	}
+	
+	if (getprop("/ECAM/to-config-flipflop") and getprop("/ECAM/to-config-normal")) {
+		toMemoLine5.msg = "    T.O CONFIG NORMAL";
+		toMemoLine5.colour = "g";
+	} else {
+		toMemoLine5.msg = "    T.O CONFIG..TEST";
+		toMemoLine5.colour = "c";
+	}
+	
+	if (getprop("/ECAM/to-config-test") and (getprop("/ECAM/warning-phase") == 2 or getprop("/ECAM/warning-phase") == 9)) {
+		setprop("/ECAM/to-memo-set", 1);
+	} else {
+		setprop("/ECAM/to-memo-set", 0);
+	}
+	
+	if (getprop("/ECAM/warning-phase") == 1 or getprop("/ECAM/warning-phase") == 3 or getprop("/ECAM/warning-phase") == 6 or getprop("/ECAM/warning-phase") == 10) {
+		setprop("/ECAM/to-memo-reset", 1);
+	} else {
+		setprop("/ECAM/to-memo-reset", 0);
+	}
+	
+	if ((getprop("/ECAM/warning-phase") == 2 and getprop("/ECAM/engine-start-time") != 0 and getprop("/ECAM/engine-start-time") + 120 < getprop("/sim/time/elapsed-sec")) or getprop("/ECAM/to-memo-flipflop")) {
+		toMemoLine1.active = 1;
+		toMemoLine2.active = 1;
+		toMemoLine3.active = 1;
+		toMemoLine4.active = 1;
+		toMemoLine5.active = 1;
+	} else {
+		ECAM_controller.warningReset(toMemoLine1);
+		ECAM_controller.warningReset(toMemoLine2);
+		ECAM_controller.warningReset(toMemoLine3);
+		ECAM_controller.warningReset(toMemoLine4);
+		ECAM_controller.warningReset(toMemoLine5);
+	}
+	
+	if (getprop("/fdm/jsbsim/gear/gear-pos-norm") == 1) {
+		ldgMemoLine1.msg = "LDG LDG GEAR DN";
+		ldgMemoLine1.colour = "g";
+	} else {
+		ldgMemoLine1.msg = "LDG LDG GEAR......DN";
+		ldgMemoLine1.colour = "c";
+	}
+	
+	if (getprop("/controls/switches/seatbelt-sign") and getprop("/controls/switches/no-smoking-sign")) {
+		ldgMemoLine2.msg = "    SIGNS ON";
+		ldgMemoLine2.colour = "g";
+	} else {
+		ldgMemoLine2.msg = "    SIGNS.........ON";
+		ldgMemoLine2.colour = "c";
+	}
+	
+	if (getprop("/controls/flight/speedbrake-arm")) {
+		ldgMemoLine3.msg = "    SPLRS ARM";
+		ldgMemoLine3.colour = "g";
+	} else {
+		ldgMemoLine3.msg = "    SPLRS........ARM";
+		ldgMemoLine3.colour = "c";
+	}
+	
+	if (getprop("/it-fbw/law") == 1 or getprop("instrumentation/mk-viii/inputs/discretes/momentary-flap-3-override")) {
+		if (getprop("/controls/flight/flap-pos") == 4) {
+			ldgMemoLine4.msg = "    FLAPS CONF 3";
+			ldgMemoLine4.colour = "g";
+		} else {
+			ldgMemoLine4.msg = "    FLAPS.....CONF 3";
+			ldgMemoLine4.colour = "c";
+		}
+	} else {
+		if (getprop("/controls/flight/flap-pos") == 5) {
+			ldgMemoLine4.msg = "    FLAPS FULL";
+			ldgMemoLine4.colour = "g";
+		} else {
+			ldgMemoLine4.msg = "    FLAPS.......FULL";
+			ldgMemoLine4.colour = "c";
+		}
+	}
+	
+	gear_agl_cur = pts.Position.gearAglFt.getValue();
+	if (gear_agl_cur < 2000) {
+		setprop("/ECAM/ldg-memo-set", 1);
+	} else {
+		setprop("/ECAM/ldg-memo-set", 0);
+	}
+	
+	if (gear_agl_cur > 2200) {
+		setprop("/ECAM/ldg-memo-reset", 1);
+	} else {
+		setprop("/ECAM/ldg-memo-reset", 0);
+	}
+	
+	if (gear_agl_cur > 2200) {
+		setprop("/ECAM/ldg-memo-2200-set", 1);
+	} else {
+		setprop("/ECAM/ldg-memo-2200-set", 0);
+	}
+	
+	if (getprop("/ECAM/warning-phase") >= 6 and getprop("/ECAM/warning-phase") <= 8) {
+		setprop("/ECAM/ldg-memo-2200-reset", 1);
+	} else {
+		setprop("/ECAM/ldg-memo-2200-reset", 0);
+	}
+	
+	if ((getprop("/ECAM/warning-phase") == 6 and getprop("/ECAM/ldg-memo-flipflop") and getprop("/ECAM/ldg-memo-2200-flipflop")) or getprop("/ECAM/warning-phase") == 7 or getprop("/ECAM/warning-phase") == 8) {
+		ldgMemoLine1.active = 1;
+		ldgMemoLine2.active = 1;
+		ldgMemoLine3.active = 1;
+		ldgMemoLine4.active = 1;
+	} else {
+		ECAM_controller.warningReset(ldgMemoLine1);
+		ECAM_controller.warningReset(ldgMemoLine2);
+		ECAM_controller.warningReset(ldgMemoLine3);
+		ECAM_controller.warningReset(ldgMemoLine4);
+	}
+}
+
 var messages_memo = func {
 	phaseVar = phaseNode.getValue();
 	if (getprop("/services/fuel-truck/enable") == 1 and leftMsgNode.getValue() != "TO-MEMO" and leftMsgNode.getValue() != "LDG-MEMO") {
diff --git a/Nasal/ECAM/ECAM-messages.nas b/Nasal/ECAM/ECAM-messages.nas
index 37dfc6ba..879ea530 100644
--- a/Nasal/ECAM/ECAM-messages.nas
+++ b/Nasal/ECAM/ECAM-messages.nas
@@ -165,6 +165,14 @@ var warnings				  = std.Vector.new([
 	var dcEmerconfig          = warning.new(msg: "ELEC DC EMER CONFIG",       colour: "a", aural: 1, light: 0, hasSubmsg: 1),
 	var dcEmerconfigManOn     = warning.new(msg: " -EMER ELEC PWR...MAN ON",   colour: "c"),
 	
+	# FCU fault
+	var fcuFault              = warning.new(msg: "AUTO FLT FCU 1+2 FAULT",    colour: "a", aural: 1, light: 1, hasSubmsg: 1),
+	var fcuFaultBaro          = warning.new(msg: " -PFD BARO REF: STD ONLY",  colour: "c"),
+	var fcuFault1             = warning.new(msg: "AUTO FLT FCU 1 FAULT",      colour: "a", hasSubmsg: 1),
+	var fcuFault1Baro         = warning.new(msg: " -BARO REF.......X CHECK",  colour: "c"),
+	var fcuFault2             = warning.new(msg: "AUTO FLT FCU 2 FAULT",      colour: "a", hasSubmsg: 1),
+	var fcuFault2Baro         = warning.new(msg: " -BARO REF.......X CHECK",  colour: "c"),
+	
 	# APU shutdown
 	var apuEmerShutdown       = warning.new(msg: "APU EMER SHUT DOWN",        colour: "a", aural: 1, light: 1, hasSubmsg: 1),
 	var apuEmerShutdownMast   = warning.new(msg: " -MASTER SW..........OFF",  colour: "c"),
@@ -183,6 +191,19 @@ var warnings				  = std.Vector.new([
 	var crgAftFireDetFault    = warning.new(msg: "AFT CRG DET FAULT",         colour: "a"), 
 ]);
 
+var configmemos               = std.Vector.new([
+	var toMemoLine1           = warning.new(msg: "T.O AUTO BRK.....MAX",      colour: "c", isMemo: 1),
+	var toMemoLine2           = warning.new(msg: "    SIGNS.........ON",      colour: "c", isMemo: 1),
+	var toMemoLine3           = warning.new(msg: "    SPLRS........ARM",      colour: "c", isMemo: 1),
+	var toMemoLine4           = warning.new(msg: "    FLAPS........T.O",      colour: "c", isMemo: 1),
+	var toMemoLine5           = warning.new(msg: "    T.O CONFIG..TEST",      colour: "c", isMemo: 1),
+	
+	var ldgMemoLine1          = warning.new(msg: "LDG LDG GEAR......DN",      colour: "c", isMemo: 1),
+	var ldgMemoLine2          = warning.new(msg: "    SIGNS.........ON",      colour: "c", isMemo: 1),
+	var ldgMemoLine3          = warning.new(msg: "    SPLRS........ARM",      colour: "c", isMemo: 1),
+	var ldgMemoLine4          = warning.new(msg: "    FLAPS.......FULL",      colour: "c", isMemo: 1),
+]);
+
 var leftmemos                 = std.Vector.new([
 	var company_alert         = warning.new(msg: "COMPANY ALERT"        ), # Not yet implemented, buzzer sound
 	var refuelg               = warning.new(msg: "REFUELG"              ),
diff --git a/Nasal/ECAM/ECAM-phases.nas b/Nasal/ECAM/ECAM-phases.nas
new file mode 100644
index 00000000..3898bcdb
--- /dev/null
+++ b/Nasal/ECAM/ECAM-phases.nas
@@ -0,0 +1,241 @@
+# A3XX FWC Phases
+
+# Copyright (c) 2019 Jonathan Redpath (legoboyvdlp)
+
+var gnd = 0;
+var twoEngOff = 0;
+var gear_agl = nil;
+var gear_comp = nil;
+var myPhase = nil;
+var eng = nil;
+var eng1epr = nil;
+var eng2epr = nil;
+var eng1n1 = nil;
+var eng2n1 = nil;
+var eng1n2 = nil;
+var eng2n2 = nil;
+var eprlim = nil;
+var master1 = nil;
+var master2 = nil;
+var n1lim = nil;
+var gear_agl_cur = nil;
+
+var FWC = {
+	Monostable: {
+		phase1: props.globals.initNode("/ECAM/phases/monostable/phase-1-300", 0, "BOOL"),
+		phase5: props.globals.initNode("/ECAM/phases/monostable/phase-5", 0, "BOOL"),
+		phase7: props.globals.initNode("/ECAM/phases/monostable/phase-7", 0, "BOOL"),
+		phase9: props.globals.initNode("/ECAM/phases/monostable/phase-9", 0, "BOOL"),
+		phase1Output: props.globals.initNode("/ECAM/phases/monostable/phase-1-output"),
+		phase5Output: props.globals.initNode("/ECAM/phases/monostable/phase-5-output"),
+		phase7Output: props.globals.initNode("/ECAM/phases/monostable/phase-7-output"),
+		phase9Output: props.globals.initNode("/ECAM/phases/monostable/phase-9-output"),
+		toPowerOutput: props.globals.getNode("/ECAM/phases/monostable/to-power-set-output"),
+		m80kt: props.globals.getNode("/ECAM/phases/monostable-80kt"),
+	},
+	Flipflop: {
+		gearSet: props.globals.initNode("/ECAM/phases/flipflop/gear-set", 0, "BOOL"),
+		gearReset: props.globals.initNode("/ECAM/phases/flipflop/gear-reset", 0, "BOOL"),
+		gearOutput: props.globals.initNode("/ECAM/phases/flipflop/gear-output", 0, "BOOL"),
+		phase2Set: props.globals.initNode("/ECAM/phases/flipflop/phase-2-set", 0, "BOOL"),
+		phase2Reset: props.globals.initNode("/ECAM/phases/flipflop/phase-2-reset", 0, "BOOL"),
+		phase2Output: props.globals.initNode("/ECAM/phases/flipflop/phase-2-output", 0, "BOOL"),
+		phase10Set: props.globals.initNode("/ECAM/phases/flipflop/phase-10-set", 0, "BOOL"),
+		phase10Reset: props.globals.initNode("/ECAM/phases/flipflop/phase-10-reset", 0, "BOOL"),
+		phase10Output: props.globals.initNode("/ECAM/phases/flipflop/phase-10-output", 0, "BOOL"),
+	},
+	Timer: {
+		eng1idle: props.globals.initNode("/ECAM/phases/timer/eng1idle", 0, "INT"),
+		eng2idle: props.globals.initNode("/ECAM/phases/timer/eng2idle", 0, "INT"),
+		eng1or2: props.globals.initNode("/ECAM/phases/timer/eng1or2", 0, "INT"),
+		eng1idleOutput: props.globals.getNode("/ECAM/phases/timer/eng1idle-output"),
+		eng2idleOutput: props.globals.getNode("/ECAM/phases/timer/eng2idle-output"),
+		eng1or2Output: props.globals.initNode("/ECAM/phases/timer/eng1or2-output", 0, "INT"),
+	},
+	speed80: props.globals.initNode("/ECAM/phases/speed-gt-80", 0, "BOOL"),
+	toPower: props.globals.initNode("/ECAM/phases/to-power-set", 0, "BOOL"),
+};
+
+var phaseLoop = func() {
+	gear_agl = pts.Position.gearAglFt.getValue();
+	gear_comp = pts.Gear.compression[1].getValue();
+	myPhase = pts.ECAM.fwcWarningPhase.getValue();
+	eng = pts.Options.eng.getValue();
+	eng1epr = pts.Engines.Engine1.epractual.getValue();
+	eng2epr = pts.Engines.Engine2.epractual.getValue();
+	eng1n1 = pts.Engines.Engine1.n1actual.getValue();
+	eng2n1 = pts.Engines.Engine2.n1actual.getValue();
+	eng1n2 = pts.Engines.Engine1.n2actual.getValue();
+	eng2n2 = pts.Engines.Engine2.n2actual.getValue();
+	master1 = pts.Controls.Engines.Engine1.cutoffSw.getBoolValue();
+	master2 = pts.Controls.Engines.Engine2.cutoffSw.getBoolValue();
+	
+	# Various things
+	if (gear_agl < 5) {
+		FWC.Flipflop.gearSet.setBoolValue(1);
+	} else {
+		FWC.Flipflop.gearSet.setBoolValue(0);
+	}
+	
+	if (!gear_comp) {
+		FWC.Flipflop.gearReset.setBoolValue(1);
+	} else {
+		FWC.Flipflop.gearReset.setBoolValue(0);
+	}
+	
+	if ((gear_agl < 5 or FWC.Flipflop.gearOutput.getBoolValue()) and gear_comp > 0) {
+		gnd = 1;
+	} else {
+		gnd = 0;
+	}
+	
+	if (eng1n2 < 59.4) {
+		FWC.Timer.eng1idle.setValue(1);
+	} else {
+		FWC.Timer.eng1idle.setValue(0);
+	}
+	
+	if (eng2n2 < 59.4) {
+		FWC.Timer.eng2idle.setValue(1);
+	} else {
+		FWC.Timer.eng2idle.setValue(0);
+	}
+	
+	if (eng1n2 >= 59.4 or eng2n2 >= 59.4) {
+		FWC.Timer.eng1or2.setValue(1);
+	} else {
+		FWC.Timer.eng1or2.setValue(0);
+	}
+	
+	if ((FWC.Timer.eng1idleOutput.getBoolValue() or master1) and (FWC.Timer.eng2idleOutput.getBoolValue() or master2)) {
+		twoEngOff = 1;
+	} else {
+		twoEngOff = 0;
+	}
+	
+	if (eng == "IAE") {
+		eprlim = getprop("/controls/engines/epr-limit");
+		if ((!getprop("/controls/engines/engine[0]/reverser") and !getprop("/controls/engines/engine[1]/reverser")) and (abs(eng1epr - eprlim) <= 0.005 or abs(eng2epr - eprlim) <= 0.005)) {
+			FWC.toPower.setBoolValue(1);
+		} else {
+			FWC.toPower.setBoolValue(0);
+		}
+	} else {
+		n1lim = getprop("/controls/engines/n1-limit");
+		if ((!getprop("/controls/engines/engine[0]/reverser") and !getprop("/controls/engines/engine[1]/reverser")) and (abs(eng1n1 - n1lim) <= 0.1 or abs(eng2n1 - n1lim) <= 0.1)) {
+			FWC.toPower.setBoolValue(1);
+		} else {
+			FWC.toPower.setBoolValue(0);
+		}
+	}
+	
+	if (pts.Instrumentation.AirspeedIndicator.indicatedSpdKt.getValue() > 80 and pts.Sim.Time.elapsedSec.getValue() > 5) {
+		FWC.speed80.setBoolValue(1);
+	} else {
+		FWC.speed80.setBoolValue(0);
+	}
+	
+	if (myPhase == 9) {
+		FWC.Monostable.phase9.setBoolValue(1);
+	} else {
+		FWC.Monostable.phase9.setBoolValue(0);
+	}
+	
+	# Phase 1 / 10 flipflop
+	if (myPhase == 9) {
+		FWC.Flipflop.phase10Set.setBoolValue(1);
+	} else {
+		FWC.Flipflop.phase10Set.setBoolValue(0);
+	}
+	
+	if (gnd and pts.Controls.Engines.Engine1.firePb.getBoolValue()) {
+		FWC.Flipflop.phase10Reset.setBoolValue(1);
+	} else {
+		FWC.Flipflop.phase10Reset.setBoolValue(0);
+	}
+	
+	if ((gnd and twoEngOff and myPhase == 9) and FWC.Flipflop.phase10Output.getBoolValue()) {
+		FWC.Monostable.phase1.setBoolValue(1);
+	}	else {
+		FWC.Monostable.phase1.setBoolValue(0);
+	}
+	
+	# Phase 2 flipflop
+	if (myPhase == 3 or myPhase == 8) {
+		FWC.Flipflop.phase2Set.setBoolValue(1);
+	} else {
+		FWC.Flipflop.phase2Set.setBoolValue(0);
+	}
+	
+	if (!FWC.Monostable.m80kt.getBoolValue() and myPhase != 9 and ((!FWC.Monostable.phase9Output.getBoolValue() and gnd) or (!FWC.Monostable.toPowerOutput.getBoolValue() and gnd))) {
+		FWC.Flipflop.phase2Reset.setBoolValue(1);
+	} else {
+		FWC.Flipflop.phase2Reset.setBoolValue(0);
+	}
+	
+	gear_agl_cur = pts.Position.gearAglFt.getValue();
+	
+	# Phase 5 monostable
+	if (FWC.toPower.getBoolValue() and (gear_agl_cur <= 1500 and !gnd)) {
+		FWC.Monostable.phase5.setBoolValue(1);
+	} else {
+		FWC.Monostable.phase5.setBoolValue(0);
+	}
+	
+	# Phase 7 monostable
+	if (!FWC.toPower.getBoolValue() and gear_agl_cur <= 1500 and gear_agl_cur <= 800 and !gnd) {
+		FWC.Monostable.phase7.setBoolValue(1);
+	} else {
+		FWC.Monostable.phase7.setBoolValue(0);
+	}
+	
+	# Actual Phases
+	if ((gnd and twoEngOff and myPhase != 9) and !FWC.Monostable.phase1Output.getBoolValue()) {
+		setPhase(1);
+	}
+	
+	if (FWC.Timer.eng1or2Output.getBoolValue() and (gnd and !FWC.toPower.getBoolValue() and !FWC.speed80.getBoolValue()) and !FWC.Flipflop.phase2Output.getBoolValue()) {
+		setPhase(2);
+	}
+	
+	if (FWC.Timer.eng1or2Output.getBoolValue() and (gnd and FWC.toPower.getBoolValue()) and !FWC.speed80.getBoolValue()) {
+		setPhase(3);
+	}
+	
+	if ((gnd and FWC.toPower.getBoolValue()) and FWC.speed80.getBoolValue()) {
+		setPhase(4);
+	}
+	
+	if (FWC.Monostable.phase5.getBoolValue() and FWC.Monostable.phase5Output.getBoolValue()) {
+		setPhase(5);
+	}
+	
+	if (!gnd and !(FWC.Monostable.phase5.getBoolValue() and FWC.Monostable.phase5Output.getBoolValue()) and !(FWC.Monostable.phase7.getBoolValue() and FWC.Monostable.phase7Output.getBoolValue())) {
+		setPhase(6);
+	}
+	
+	if ((FWC.Monostable.phase7.getBoolValue() and FWC.Monostable.phase7Output.getBoolValue()) and myPhase != 8) {
+		setPhase(7);
+	}
+	
+	if (!FWC.toPower.getBoolValue() and FWC.speed80.getBoolValue() and gnd) {
+		setPhase(8);
+	}
+	
+	if (FWC.Flipflop.phase2Output.getBoolValue() and (gnd and !FWC.toPower.getBoolValue() and !FWC.speed80.getBoolValue()) and FWC.Timer.eng1or2.getBoolValue()) {
+		setPhase(9);
+	}
+	
+	if ((gnd and twoEngOff and myPhase == 9) and FWC.Monostable.phase1Output.getBoolValue()) {
+		setPhase(10);
+	}
+}
+
+var _lastPhase = nil;
+var setPhase = func(newPhase) {
+	if (newPhase >= 1 and newPhase <= 10 and _lastPhase != newPhase) {
+		pts.ECAM.fwcWarningPhase.setValue(newPhase);
+		print("Phase " ~ newPhase);
+		_lastPhase = newPhase;
+	}
+}
\ No newline at end of file
diff --git a/Nasal/FMGC.nas b/Nasal/FMGC.nas
index 6d489fdc..147478d6 100644
--- a/Nasal/FMGC.nas
+++ b/Nasal/FMGC.nas
@@ -179,7 +179,7 @@ var masterFMGC = maketimer(0.2, func {
 	modeI = getprop("/it-autoflight/mode/vert");
 	gs = getprop("/velocities/groundspeed-kt");
 	alt = getprop("/instrumentation/altimeter/indicated-altitude-ft");
-	aglalt = getprop("/position/gear-agl-ft");
+	aglalt = pts.Position.gearAglFt.getValue();
 	cruiseft = getprop("/FMGC/internal/cruise-ft");
 	cruiseft_b = getprop("/FMGC/internal/cruise-ft") - 200;
 	newcruise = getprop("/it-autoflight/internal/alt");
@@ -288,7 +288,7 @@ var masterFMGC = maketimer(0.2, func {
 	if (gear0 == 1 and (state1 == "MCT" or state1 == "MAN THR" or state1 == "TOGA") and (state2 == "MCT" or state2 == "MAN THR" or state2 == "TOGA") and flaps < 5) {
 		setprop("/FMGC/status/to-state", 1);
 	}
-	if (getprop("/position/gear-agl-ft") >= 55) {
+	if (pts.Position.gearAglFt.getValue() >= 55) {
 		setprop("/FMGC/status/to-state", 0);
 	}
 });
diff --git a/Nasal/fadec-common.nas b/Nasal/fadec-common.nas
index cdc4bd0a..5af4e4d0 100644
--- a/Nasal/fadec-common.nas
+++ b/Nasal/fadec-common.nas
@@ -199,9 +199,9 @@ var atoff_request = func {
 	state1 = getprop("/systems/thrust/state1");
 	state2 = getprop("/systems/thrust/state2");
 	if ((state1 == "IDLE") and (state2 == "IDLE") and (getprop("/systems/thrust/alpha-floor") == 0) and (getprop("/systems/thrust/toga-lk") == 0)) {
-		if (getprop("/it-autoflight/input/athr") == 1 and getprop("/position/gear-agl-ft") > 50) {
+		if (getprop("/it-autoflight/input/athr") == 1 and pts.Position.gearAglFt.getValue() > 50) {
 			fcu.athrOff("soft");
-		} elsif (getprop("/position/gear-agl-ft") < 50) {
+		} elsif (pts.Position.gearAglFt.getValue() < 50) {
 			fcu.athrOff("none");
 		}
 	}
@@ -280,7 +280,7 @@ var thrust_loop = maketimer(0.04, func {
 	togaLock = alphaProt - 1;
 	if (getprop("/gear/gear[1]/wow") == 0 and getprop("/gear/gear[2]/wow") == 0 and getprop("/it-fbw/law") == 0 and (getprop("/systems/thrust/eng-out") == 0 or (getprop("/systems/thrust/eng-out") == 1 and flaps == 0)) and getprop("/systems/fadec/n1mode1") == 0 
 	and getprop("/systems/fadec/n1mode2") == 0) {
-		if (alpha > alphaProt and getprop("/position/gear-agl-ft") >= 100) {
+		if (alpha > alphaProt and pts.Position.gearAglFt.getValue() >= 100) {
 			setprop("/systems/thrust/alpha-floor", 1);
 			setprop("/systems/thrust/toga-lk", 0);
 			setprop("/it-autoflight/input/athr", 1);
diff --git a/Nasal/libraries.nas b/Nasal/libraries.nas
index 3e5f489e..774b751a 100644
--- a/Nasal/libraries.nas
+++ b/Nasal/libraries.nas
@@ -312,6 +312,14 @@ canvas.Element.setVisible = func(vis) {
 	me._lastVisible = vis;
 	me.setBool("visible", vis);
 };
+canvas.Element._lastX = nil;
+canvas.Element._lastY = nil;
+canvas.Element.setScale = func(x, y) {
+	if (x == me._lastX and y == me._lastY) {return me;}
+	me._lastX = x;
+	me._lastY = y;
+	me.setScale(x, y);
+};
 
 # In air, flaps 1 is slats only. On ground, it is slats and flaps.
 
diff --git a/Nasal/property-tree-setup.nas b/Nasal/property-tree-setup.nas
new file mode 100644
index 00000000..4ed28c80
--- /dev/null
+++ b/Nasal/property-tree-setup.nas
@@ -0,0 +1,62 @@
+# A320 Property Tree Setup
+# Copyright (c) 2019 Joshua Davidson (Octal450)
+# Modified by Jonathan Redpath for A320
+# Nodes organized like property tree, except when lots of identical (example: Gear wow), where vectors are used to make it easier
+# Anything that says Temp is set by another file to avoid multiple getValue calls
+# Usage Example: pts.Class.SubClass.node.getValue()
+
+var Controls = {
+	Engines: {
+		Engine1: {
+			cutoffSw: props.globals.getNode("/controls/engines/engine[0]/cutoff-switch"),
+			firePb: props.globals.getNode("/controls/engines/engine[0]/fire-btn"),
+		},
+		Engine2: {
+			cutoffSw: props.globals.getNode("/controls/engines/engine[1]/cutoff-switch"),
+			firePb: props.globals.getNode("/controls/engines/engine[1]/fire-btn"),
+		},
+	},
+};
+
+var ECAM = {
+	fwcWarningPhase: props.globals.initNode("/ECAM/warning-phase", 1, "INT"),
+};
+
+var Engines = {
+	Engine1: {
+		epractual: props.globals.getNode("/engines/engine[0]/epr-actual"),
+		n1actual: props.globals.getNode("/engines/engine[0]/n1-actual"),
+		n2actual: props.globals.getNode("/engines/engine[0]/n2-actual"),
+	},
+	Engine2: {
+		epractual: props.globals.getNode("/engines/engine[1]/epr-actual"),
+		n1actual: props.globals.getNode("/engines/engine[1]/n1-actual"),
+		n2actual: props.globals.getNode("/engines/engine[1]/n2-actual"),
+	},
+};
+
+var Gear = {
+	compression: [props.globals.getNode("/gear/gear[0]/compression-norm"),props.globals.getNode("/gear/gear[1]/compression-norm"),props.globals.getNode("/gear/gear[2]/compression-norm")],
+};
+
+var Instrumentation = {
+	AirspeedIndicator: {
+		indicatedSpdKt: props.globals.getNode("/instrumentation/airspeed-indicator/indicated-speed-kt"),
+	},
+};
+
+var Options = {
+	eng: props.globals.getNode("/options/eng"),
+};
+
+var Position = {
+	gearAglFt: props.globals.getNode("/position/gear-agl-ft"),
+};
+
+var Sim = {
+	Time: {
+		elapsedSec: props.globals.getNode("/sim/time/elapsed-sec"),
+	},
+};
+
+setprop("/systems/acconfig/property-tree-setup-loaded", 1);
diff --git a/Systems/a320-fwc.xml b/Systems/a320-fwc.xml
new file mode 100644
index 00000000..9a47e538
--- /dev/null
+++ b/Systems/a320-fwc.xml
@@ -0,0 +1,31 @@
+<!-- Airbus A320 FWC -->
+
+<!-- Copyright (c) 2019 Jonathan Redpath -->
+
+<system name="A320: FWC">
+
+	<channel name="FWC">
+		
+		<actuator name="/ECAM/phases/timer/eng1idle-output">
+            <description>Timer for the ECAM system</description>
+            <input>/ECAM/phases/timer/eng1idle</input>
+            <rate_limit sense="decr">100</rate_limit> <!-- Instant -->
+            <rate_limit sense="incr">0.033</rate_limit> <!-- 30 seconds -->
+        </actuator>
+		
+		<actuator name="/ECAM/phases/timer/eng2idle-output">
+            <description>Timer for the ECAM system</description>
+            <input>/ECAM/phases/timer/eng2idle</input>
+            <rate_limit sense="decr">100</rate_limit> <!-- Instant -->
+            <rate_limit sense="incr">0.033</rate_limit> <!-- 30 seconds -->
+        </actuator>
+		
+		<actuator name="/ECAM/phases/timer/eng1or2-output">
+            <description>Timer for the ECAM system</description>
+            <input>/ECAM/phases/timer/eng1or2</input>
+            <rate_limit sense="decr">100</rate_limit> <!-- Instant -->
+            <rate_limit sense="incr">0.033</rate_limit> <!-- 30 seconds -->
+        </actuator>
+	</channel>
+
+</system>
diff --git a/Systems/upper-ecam.xml b/Systems/upper-ecam.xml
index aace9ad1..9dcc243c 100644
--- a/Systems/upper-ecam.xml
+++ b/Systems/upper-ecam.xml
@@ -452,4 +452,152 @@
 		</R>
 		<output>/systems/electrical/some-electric-thingie/generator-2-reset</output>
 	</flipflop>
+	
+	<flipflop>
+		<type>RS</type>
+		<S>
+			<property>/ECAM/to-config-set</property>
+		</S>
+		<R>
+			<property>/ECAM/to-config-reset</property>
+		</R>
+		<output>/ECAM/to-config-flipflop</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>RS</type>
+		<S>
+			<property>/ECAM/to-memo-set</property>
+		</S>
+		<R>
+			<property>/ECAM/to-memo-reset</property>
+		</R>
+		<output>/ECAM/to-memo-flipflop</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>SR</type>
+		<S>
+			<property>/ECAM/ldg-memo-set</property>
+		</S>
+		<R>
+			<property>/ECAM/ldg-memo-reset</property>
+		</R>
+		<output>/ECAM/ldg-memo-flipflop</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>RS</type>
+		<S>
+			<property>/ECAM/ldg-memo-2200-set</property>
+		</S>
+		<R>
+			<property>/ECAM/ldg-memo-2200-reset</property>
+		</R>
+		<output>/ECAM/ldg-memo-2200-flipflop</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>SR</type>
+		<S>
+			<property>/ECAM/phases/flipflop/gear-set</property>
+		</S>
+		<R>
+			<property>/ECAM/phases/flipflop/gear-reset</property>
+		</R>
+		<output>/ECAM/phases/flipflop/gear-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>SR</type>
+		<S>
+			<property>/ECAM/phases/flipflop/phase-2-set</property>
+		</S>
+		<R>
+			<property>/ECAM/phases/flipflop/phase-2-reset</property>
+		</R>
+		<output>/ECAM/phases/flipflop/phase-2-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>RS</type>
+		<S>
+			<property>/ECAM/phases/flipflop/phase-10-set</property>
+		</S>
+		<R>
+			<property>/ECAM/phases/flipflop/phase-10-reset</property>
+		</R>
+		<output>/ECAM/phases/flipflop/phase-10-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>monostable</type>
+		<time>
+			<value>2.0</value>
+		</time>
+		<S>
+			<not>
+				<property>/ECAM/phases/speed-gt-80</property>
+			</not>
+		</S>
+		<output>/ECAM/phases/monostable-80kt</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>monostable</type>
+		<time>
+			<value>300.0</value>
+		</time>
+		<S>
+			<property>/ECAM/phases/monostable/phase-1-300</property>
+		</S>
+		<output>/ECAM/phases/monostable/phase-1-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>monostable</type>
+		<time>
+			<value>120.0</value>
+		</time>
+		<S>
+			<property>/ECAM/phases/monostable/phase-5</property>
+		</S>
+		<output>/ECAM/phases/monostable/phase-5-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>monostable</type>
+		<time>
+			<value>180.0</value>
+		</time>
+		<S>
+			<property>/ECAM/phases/monostable/phase-7</property>
+		</S>
+		<output>/ECAM/phases/monostable/phase-7-output</output>
+	</flipflop>
+	
+	<!-- falling edge detector - take inverse of following -->
+	<flipflop>
+		<type>monostable</type>
+		<inverted type="bool">true</inverted>
+		<time>
+			<value>3.0</value>
+		</time>
+		<S>
+			<property>/ECAM/phases/monostable/phase-9</property>
+		</S>
+		<output>/ECAM/phases/monostable/phase-9-output</output>
+	</flipflop>
+	
+	<flipflop>
+		<type>monostable</type>
+		<inverted type="bool">true</inverted>
+		<time>
+			<value>1.0</value>
+		</time>
+		<S>
+			<property>/ECAM/phases/to-power-set</property>
+		</S>
+		<output>/ECAM/phases/monostable/to-power-set-output</output>
+	</flipflop>
 </PropertyList>
diff --git a/revision.txt b/revision.txt
index 62f94575..c7930257 100644
--- a/revision.txt
+++ b/revision.txt
@@ -1 +1 @@
-6
\ No newline at end of file
+7
\ No newline at end of file