diff --git a/Aircraft/Generic/an_spn_46.nas b/Aircraft/Generic/an_spn_46.nas
new file mode 100644
index 000000000..537f857d3
--- /dev/null
+++ b/Aircraft/Generic/an_spn_46.nas
@@ -0,0 +1,330 @@
+#---------------------------------------------------------------------------
+#
+#	Title                : AN/SPN-46 Precision Approach Landing System (PALS)
+#
+#	File Type            : Implementation File
+#
+#	Description          : Representative emulation of the functions of the AN/SPN-46 using emesary
+#                        : Where an AN/SPN-46 is required it is sufficient to instantiate a ANSPN46_System connected to the instantiator model.
+#	                     : Register with an instance of a Transmitter, and provide a Receive method, periodically send out Active messages
+#                        : expecting ActiveResponse messages which may result in a Communication.
+#                        : This is implemented as a set of messages that models the operation of the PALS
+#  
+#   References           : http://trace.tennessee.edu/cgi/viewcontent.cgi?article=3297&context=utk_gradthes
+#                        : http://www.navair.navy.mil/index.cfm?fuseaction=home.displayPlatform&key=E8D18768-14B6-4CF5-BAB5-12B009070CFC
+#                        : http://www.afceaboston.com/documents/events/cnsatm2010/Briefs/4%20-%20Friday/03-Navy_Landing_Systems_Roadmap-(CDR%20Easler).pdf
+#
+#	Author               : Richard Harrison (richard@zaretto.com)
+#
+#	Creation Date        : 29 January 2016
+#
+#	Version              : 4.8
+#
+#  Copyright � 2016 Richard Harrison           Released under GPL V2
+#
+#---------------------------------------------------------------------------*/
+#Message Reference:
+#---------------------------------------------------------------------------*/
+# Notification 1 ANSPN46ActiveNotification  from carrier to aircraft
+#   Transmitted via GlobalTransmitter at 1hz
+#    - carrier position
+#    - beam start
+#    - beam angle
+#    - channel / frequency information
+#    - beam range / power
+#
+# Notification 2 - from aircraft to carrier
+#    - aircraft position
+#    - radar return size
+#    - aircraft altitude, heading, velocity
+#    - respose indicating tuned or not
+#
+# Notification 3 - from carrier to aircraft
+#    - lateral deviation 
+#    - vertical deviation
+#    - LSO information / messages
+#    - system status
+#    - lateral 
+#
+#Operation:
+#---------------------
+# The ANSPN64 system will send periodically send out a ANSPN46ActiveNotification
+# the rest of the logic within this system related to aircraft will be handled when
+# the ANSPN46ActiveResponseNotification - which itself in turn will send out a ANSPN46CommunicationNotification
+#----------------------
+# NOTE: to avoid garbage collection all of the notifications that are sent out are created during construction
+#       and simply modified prior to sending. This works because emesary is synchronous and therefore the state
+#       and lifetime are known.
+
+#
+# Notification(1) from carrier to any aircraft within range.
+#
+var ANSPN46ActiveNotification = 
+{
+    # Create a new active notification notification. Aircraft will respond to this.
+    # param(_anspn46_system): instance of ANSPN46_System which will send the notification 
+    new: func(_anspn46_system)
+    {
+        var new_class = emesary.Notification.new("ANSPN46ActiveNotification", _anspn46_system.Ident);
+        new_class.ANSPN46_system = _anspn46_system;
+
+        #
+        # Set notification properties from the ANSPN46_System. 
+        new_class.set_from = func(_anspn)
+        {
+            me.Position = _anspn.GetCarrierPosition();
+            me.BeamPosition = _anspn.GetTDZPosition();
+            me.BeamAngle = 35;
+            me.Channel = _anspn.GetChannel();
+            me.BeamRange = 35; ##nm
+            me.BeamPower = 999; ## mw ???
+        };
+        new_class.set_from(_anspn46_system);
+        return new_class;
+    },
+};
+
+# Notification(2) - from aircraft to carrier sent in response to Notification(1) above
+#
+var ANSPN46ActiveResponseNotification = 
+{
+    new: func(_ident)
+    {
+        var new_class = emesary.Notification.new("ANSPN46ActiveResponseNotification", _ident);
+        new_class.Respond = func(_msg)
+        {
+            new_class.Position = geo.aircraft_position();
+            new_class.Heading = getprop("orientation/heading-deg");
+            new_class.RadarReturnStrength = 1; # normalised value based on RCS beam power etc.
+            new_class.Tuned = 0; # 0 or 1
+            new_class.ufps = getprop("velocities/uBody-fps");
+            return me;
+        }
+        return new_class;
+    },
+};
+
+# Notification 3 - from carrier to aircraft as a result of active response notification
+#    - only sent if the aircraft is set to the same channel that we are transmitting on
+#
+var ANSPN46CommunicationNotification = 
+{
+    new: func(_ident, _anspn46_system)
+    {
+        var new_class = emesary.Notification.new("ANSPN46CommunicationNotification", _ident);
+        new_class.Model = _anspn46_system.Model;
+
+        new_class.set_from = func(_ident, _msg, _anspn46_system)
+        {
+            var carrier_ara_63_position = _anspn46_system.GetCarrierPosition();
+            var carrier_heading = _anspn46_system.GetCarrierHeading();
+            var carrier_ara_63_heading = 0;
+
+# relative offset of the course to the tdz
+# according to my measurements the Nimitz class is 8.1362114 degrees (measured 178 vs carrier 200 allowing for local magvar -13.8637886)
+# i.e. this value is from tuning rather than calculation
+
+            if (carrier_heading != nil)
+                carrier_ara_63_heading = carrier_heading.getValue() - 8.1362114;
+
+            var range = _msg.Position.distance_to(carrier_ara_63_position);
+            var bearing_to = _msg.Position.course_to(carrier_ara_63_position);
+            var deviation = bearing_to - carrier_ara_63_heading;
+
+            deviation = deviation *0.1;
+            me.ReturnPosition = _msg.Position;
+            me.ReturnBearing = getprop("orientation/heading-deg");
+
+# the AN/SPN 46 has a 20nm range with a 3 degree beam; ref: F14-AAD-1 17.3.2
+            if (range < 37000 and abs(deviation) < 3) 
+            {
+                var FD_TAN3DEG = math.tan(3.0 / 57.29577950560105);
+                var deck_height=20;
+                var gs_height = ((range*FD_TAN3DEG)) + deck_height;
+                var gs_deviation = (gs_height - _msg.Position.alt()) / 42.0; 
+
+                if (gs_deviation > 1)
+                    gs_deviation = 1;
+                else if (gs_deviation < -1) 
+                    gs_deviation = -1;
+
+# if not in range message will not be transmitted.
+                me.InRange = 1; 
+
+# calculate the deviation from the ideal approach
+                me.VerticalAdjustmentCommanded = gs_deviation;
+                me.HorizontalAdjustmentCommanded = deviation;
+
+                me.LateralDeviation = deviation;
+                me.VerticalDeviation = gs_deviation;
+
+                me.Distance = range;
+
+                me.SignalQualityNorm = 1;
+
+#
+# work out the rough ETA for the 10 seconds light, and use this
+# to decide whether or not to waveoff
+                var eta = range / (_msg.ufps / 3.281);
+
+                if(eta <= 10 and range < 800 and range > 150)
+                {
+                    me.TenSeconds = 1;
+                    if(math.abs(deviation) > 0.2 or math.abs(gs_deviation) > 0.2)
+                    {
+                        me.WaveOff = 1;
+                    }
+                    else
+                    {
+                        me.WaveOff = 0;
+                    }
+                }
+                else
+                {
+                    me.TenSeconds = 0;
+                    me.WaveOff = 0;
+                }
+                me.LSOMessage = "";
+                me.SystemStatus = "OK"; # Wave off, error, etcc.
+                                            }
+            else
+            {
+#
+# No response will be sent when not in range; so ensure values are all cleared.
+                me.InRange = 0; 
+                me.VerticalAdjustmentCommanded = 0;
+                me.HorizontalAdjustmentCommanded = 0;
+                me.SignalQualityNorm =0;
+                me.Distance = -10000000000;
+                me.TenSeconds = 0;
+                me.WaveOff = 0;
+                me.InRange = 0;
+                me.VerticalDeviation = 0;
+                me.LateralDeviation = 0;
+                me.LSOMessage = "";
+                me.SystemStatus = "";
+            }
+        };
+        return new_class;
+    },
+};
+
+#
+# The main AN/SPN46 system implemented using emesary.
+# Periodically the Update method should be called, which will
+# send out a notification via the global transmitter so that aircraft within range
+# can respond. This is similar to a radar transmit and return.
+# There should be an instance of this class created in the nasal section of the model xml
+# Once an aircraft is within range it will receive guidance that can be displayed.
+# It is the responsibility of the AN/SPN system to decided whether a craft is within range.
+# It is the responsibility of the aircraft receiver to indicate whether it is tuned in or not
+# if it the aircraft is not tuned into the right channel the receiver (e.g. ARA-63) will not receive anything; however
+# the AN/SPN system (being a radar) will still have guidance information that could be relayed over the
+# comms channel or displayed on a radar display on the carrier.
+#
+var ANSPN46_System = 
+{
+    new: func(_ident,_model)
+    {
+        print("AN/SNP46 created for "~_ident);
+
+        var new_class = emesary.Recipient.new("ANSPN46_System "~_ident);
+
+        new_class.ara_63_position = geo.Coord.new();
+        new_class.Model = _model;
+        new_class.communicationNotification = ANSPN46CommunicationNotification.new(new_class.Ident, new_class);
+        new_class.Channel = 2;
+        new_class.UpdateRate = 10;
+
+#-------------------------------------------
+# Receive override:
+# Iinterested in receiving ANSPN46ActiveResponseNotification. When we get
+# one of these we can respond with a CommunicationNotification
+
+        new_class.Receive = func(notification)
+        {
+            if (notification.Type == "ANSPN46ActiveResponseNotification")
+            {
+                if (notification.Tuned)
+                {
+                    me.communicationNotification.set_from(me.Ident, notification, me);
+                    if(me.communicationNotification.InRange)
+                    {
+                        me.UpdateRate = 0.2;
+                        emesary.GlobalTransmitter.NotifyAll(me.communicationNotification);
+                    }
+                }
+                return emesary.Transmitter.ReceiptStatus_OK;
+            }
+            return emesary.Transmitter.ReceiptStatus_NotProcessed;
+        }
+#
+# Interface methods
+#-----------------------------
+# Required interface to get the current carrier position
+        new_class.GetCarrierPosition = func()
+        {
+            var x = me.Model.getNode("position/global-x").getValue() + 88.7713542;
+            var y = me.Model.getNode("position/global-y").getValue() + 18.74631309;
+            var z = me.Model.getNode("position/global-z").getValue() + 115.6574875;
+            me.ara_63_position.set_xyz(x, y, z);
+            return me.ara_63_position;
+        };
+#
+# Interface to get the carrier heading
+        new_class.GetCarrierHeading = func()
+        {
+            return me.Model.getNode("orientation/true-heading-deg");
+        };
+#
+# offset of the TDZ (wires) from the carrier centre
+        new_class.GetTDZPosition = func
+        {
+            return me.ara_63_position;
+        };
+#
+# radar beam angle
+        new_class.GetUpdateRate = func
+        {
+            return me.UpdateRate;
+        };
+        new_class.BeamAngle = func
+        {
+            return 30;
+        };
+#
+# currently transmitting channel number.
+        new_class.GetChannel = func
+        {
+            return me.Channel;
+        };
+        new_class.SetChannel = func(v)
+        {
+            me.Channel = v;
+        };
+#
+# main entry point. The object itself will manage the update rate - but it is
+# up to the caller to use this rate
+        new_class.Update = func
+        {
+            # fill in properties of message
+            me.msg.set_from(me);
+            
+            #
+            # manage the update rate; increase each frame until we get to 10 seconds
+            # this will be reset if we receive something back from the aircraft.
+            if (me.UpdateRate < 10)
+                me.UpdateRate = me.UpdateRate+1;
+#            print("AN/SPN 46 : update from",me.Ident," rate=",me.UpdateRate);
+            return emesary.GlobalTransmitter.NotifyAll(me.msg);
+        };
+
+#
+# create the message that will be used to notify of an active carrier. This needs to be done after the methods 
+# have been created as it references them. Implemented like this to reduce garbage collection
+        new_class.msg = ANSPN46ActiveNotification.new(new_class);
+
+        emesary.GlobalTransmitter.Register(new_class);
+        return new_class;
+    },
+}
diff --git a/Models/Geometry/Clemenceau/Clemenceau.xml b/Models/Geometry/Clemenceau/Clemenceau.xml
index fe05b6b37..fca66b961 100644
--- a/Models/Geometry/Clemenceau/Clemenceau.xml
+++ b/Models/Geometry/Clemenceau/Clemenceau.xml
@@ -13,6 +13,32 @@
 <PropertyList>
 
 	<path>clem-superstructure.ac</path>
+
+    <nasal>
+        <load>
+            <![CDATA[ 
+            # add AN/SPN-46 see http://chateau-logic.com/content/emesary-nasal-implementation-flightgear
+            var self = cmdarg();
+
+            fn_an_spn_46 = getprop("/sim/fg-root") ~ "/Aircraft/Generic/an_spn_46.nas";
+            io.load_nasal(fn_an_spn_46, "an_spn_46");
+            var anspn = an_spn_46.ANSPN46_System.new("Clemenceau", self);
+            anspn.SetChannel(2);
+            var an_spn_46_timer = maketimer(6, func {
+                anspn.Update();
+                an_spn_46_timer.restart(anspn.GetUpdateRate());
+            });
+            an_spn_46_timer.restart(6);
+        ]]>
+        </load>
+
+        <unload>
+            <![CDATA[ 
+            an_spn_46_timer.stop();
+            ]]>
+        </unload>
+    </nasal>
+    
 	<texture-path>Textures</texture-path>
  	<offsets>
 	 	<z-m>0</z-m>
diff --git a/Models/Geometry/Nimitz/eisenhower.xml b/Models/Geometry/Nimitz/eisenhower.xml
index a625091aa..5e5ab1790 100644
--- a/Models/Geometry/Nimitz/eisenhower.xml
+++ b/Models/Geometry/Nimitz/eisenhower.xml
@@ -8,7 +8,32 @@ apart from most of the very excellent textures, remain. -->
 	<status>early-production</status>
 	<path>nimitz.ac</path>
 
-	<!-- crew to be added later
+    <nasal>
+        <load>
+            <![CDATA[ 
+
+            var self = cmdarg();
+            print("Model load Nimitz ", self.getPath());
+
+            fn_an_spn_46 = getprop("/sim/fg-root") ~ "/Aircraft/Generic/an_spn_46.nas";
+            io.load_nasal(fn_an_spn_46, "an_spn_46");
+            var anspn = an_spn_46.ANSPN46_System.new("Eisenhower", self);
+            anspn.SetChannel(2);
+            var an_spn_46_timer = maketimer(6, func {
+                anspn.Update();
+                an_spn_46_timer.restart(anspn.GetUpdateRate());
+            });
+            an_spn_46_timer.restart(6);
+        ]]>
+        </load>
+
+        <unload>
+            <![CDATA[ 
+            an_spn_46_timer.stop();
+            ]]>
+        </unload>
+    </nasal>
+    <!-- crew to be added later
 
     <model>
       <path>Models/Geometry/Nimitz/Crew/crew.xml</path>
diff --git a/Models/Geometry/Nimitz/nimitz.xml b/Models/Geometry/Nimitz/nimitz.xml
index db63b2ff0..8b2071632 100644
--- a/Models/Geometry/Nimitz/nimitz.xml
+++ b/Models/Geometry/Nimitz/nimitz.xml
@@ -8,7 +8,32 @@ apart from most of the very excellent textures, remain. -->
 	<status>early-production</status>
 	<path>nimitz.ac</path>
 
-	<!-- crew to be added later
+    <nasal>
+        <load>
+            <![CDATA[ 
+
+            var self = cmdarg();
+            print("Model load Nimitz ", self.getPath());
+
+            fn_an_spn_46 = getprop("/sim/fg-root") ~ "/Aircraft/Generic/an_spn_46.nas";
+            io.load_nasal(fn_an_spn_46, "an_spn_46");
+            var anspn = an_spn_46.ANSPN46_System.new("Nimitz", self);
+            anspn.SetChannel(2);
+            var an_spn_46_timer = maketimer(6, func {
+                anspn.Update();
+                an_spn_46_timer.restart(anspn.GetUpdateRate());
+            });
+            an_spn_46_timer.restart(6);
+        ]]>
+        </load>
+
+        <unload>
+            <![CDATA[ 
+            an_spn_46_timer.stop();
+            ]]>
+        </unload>
+    </nasal>
+    <!-- crew to be added later
     <model>
       <path>Models/Geometry/Nimitz/Crew/crew.xml</path>
     </model>
diff --git a/Models/Geometry/Nimitz/vinson.xml b/Models/Geometry/Nimitz/vinson.xml
index ec74004b4..6aead3d7f 100644
--- a/Models/Geometry/Nimitz/vinson.xml
+++ b/Models/Geometry/Nimitz/vinson.xml
@@ -10,91 +10,104 @@ apart from most of the very excellent textures, remain. -->
 
 	<nasal>
 		<load>
-			print("LOAD Vinson ", cmdarg().getPath());
+            <![CDATA[ 
+            print("LOAD Vinson ", cmdarg().getPath());
 
-			var fg_root = getprop("/sim/fg-root");
-			var self = cmdarg();
-			var control_node = self.getNode("controls/turn-to-base-course", 1);
-			var pos_node = self.getNode("sim/antenna-pos-norm", 1);
-			pos_node.setDoubleValue(0);
-			var turn_old = 1;
+            var fg_root = getprop("/sim/fg-root");
+            var self = cmdarg();
+            var control_node = self.getNode("controls/turn-to-base-course", 1);
+            var pos_node = self.getNode("sim/antenna-pos-norm", 1);
+            pos_node.setDoubleValue(0);
+            var turn_old = 1;
 
-			########
-			# properties used to handle rendering, lighting and to control the Pack-Park
-			# Due to a change in MPcarrier system ?
+            # add AN/SPN-46 see http://chateau-logic.com/content/emesary-nasal-implementation-flightgear
+            fn_an_spn_46 = getprop("/sim/fg-root") ~ "/Aircraft/Generic/an_spn_46.nas";
+            io.load_nasal(fn_an_spn_46, "an_spn_46");
+            var anspn = an_spn_46.ANSPN46_System.new("Eisenhower", self);
+            anspn.SetChannel(2);
+            # not using the main update as need to keep the scheduling that an_spn_46 requests.
+            var an_spn_46_timer = maketimer(6, func {
+                anspn.Update();
+                an_spn_46_timer.restart(anspn.GetUpdateRate());
+            });
+            an_spn_46_timer.restart(6);
+            
+            ########
+            # properties used to handle rendering, lighting and to control the Pack-Park
+            # Due to a change in MPcarrier system ?
 
-			var rembrandt_node = self.getNode("sim/rendering/rembrandt/enabled", 1);
-			var sunAngleRad_node = self.getNode("sim/time/sun-angle-rad", 1);
-			var deckPark_node = self.getNode("sim/current-view/deck-park",1);
+            var rembrandt_node = self.getNode("sim/rendering/rembrandt/enabled", 1);
+            var sunAngleRad_node = self.getNode("sim/time/sun-angle-rad", 1);
+            var deckPark_node = self.getNode("sim/current-view/deck-park",1);
 
-			########
-			# properties used to calculate rel wind for the bow-wave shader
+            ########
+            # properties used to calculate rel wind for the bow-wave shader
 
-			var speed_Node = self.getNode("velocities/speed-kts", 1);
-			var hdg_Node = self.getNode("orientation/true-heading-deg", 1);
-			var wind_speed_Node = self.getNode("environment/rel-wind-speed-kts", 1);
-			wind_speed_Node.setDoubleValue(0);
+            var speed_Node = self.getNode("velocities/speed-kts", 1);
+            var hdg_Node = self.getNode("orientation/true-heading-deg", 1);
+            var wind_speed_Node = self.getNode("environment/rel-wind-speed-kts", 1);
+            wind_speed_Node.setDoubleValue(0);
 
-			########
-			# properties to control the E2C
+            ########
+            # properties to control the E2C
 
-			var gear0_Node = self.getNode("gear/gear[0]/position-norm", 1);
-			gear0_Node.setDoubleValue(1);
+            var gear0_Node = self.getNode("gear/gear[0]/position-norm", 1);
+            gear0_Node.setDoubleValue(1);
 
-			var gear1_Node = self.getNode("gear/gear[1]/position-norm", 1);
-			gear1_Node.setDoubleValue(1);
+            var gear1_Node = self.getNode("gear/gear[1]/position-norm", 1);
+            gear1_Node.setDoubleValue(1);
 
-			var gear2_Node = self.getNode("gear/gear[2]/position-norm", 1);
-			gear2_Node.setDoubleValue(1);
+            var gear2_Node = self.getNode("gear/gear[2]/position-norm", 1);
+            gear2_Node.setDoubleValue(1);
 
-			var compression0_Node = self.getNode("gear/gear[0]/compression-norm", 1);
-			compression0_Node.setDoubleValue(0);
+            var compression0_Node = self.getNode("gear/gear[0]/compression-norm", 1);
+            compression0_Node.setDoubleValue(0);
 
-			var compression1_Node = self.getNode("gear/gear[1]/compression-norm", 1);
-			compression1_Node.setDoubleValue(0.9);
+            var compression1_Node = self.getNode("gear/gear[1]/compression-norm", 1);
+            compression1_Node.setDoubleValue(0.9);
 
-			var compression2_Node = self.getNode("gear/gear[2]/compression-norm", 1);
-			compression2_Node.setDoubleValue(0.9);
+            var compression2_Node = self.getNode("gear/gear[2]/compression-norm", 1);
+            compression2_Node.setDoubleValue(0.9);
 
-			var wingfold_Node = self.getNode("surface-positions/wing-fold-pos-norm", 1);
-			wingfold_Node.setDoubleValue(1.0);
+            var wingfold_Node = self.getNode("surface-positions/wing-fold-pos-norm", 1);
+            wingfold_Node.setDoubleValue(1.0);
 
-			var rpm0_Node = self.getNode("engines/engine[0]/rpm", 1);
-			rpm0_Node.setDoubleValue(0.15);
+            var rpm0_Node = self.getNode("engines/engine[0]/rpm", 1);
+            rpm0_Node.setDoubleValue(0.15);
 
-			var rpm1_Node = self.getNode("engines/engine[1]/rpm", 1);
-			rpm1_Node.setDoubleValue(0.17);
+            var rpm1_Node = self.getNode("engines/engine[1]/rpm", 1);
+            rpm1_Node.setDoubleValue(0.17);
 
-			########
-			# the main loop
+            ########
+            # the main loop
 
-			var update = func {
-			var turn = control_node.getValue();
-			var value = wind_speed_Node.getValue();
-			setprop("/environment/Vinson/rel-wind-speed-kts", value);
-			value = speed_Node.getValue();
-			setprop("/environment/Vinson/spd-kt", value);
-			value = hdg_Node.getValue();
-			setprop("/environment/Vinson/hdg-deg", value);
+            var update = func {
+            var turn = control_node.getValue();
+            var value = wind_speed_Node.getValue();
+            setprop("/environment/Vinson/rel-wind-speed-kts", value);
+            value = speed_Node.getValue();
+            setprop("/environment/Vinson/spd-kt", value);
+            value = hdg_Node.getValue();
+            setprop("/environment/Vinson/hdg-deg", value);
 
-			value = getprop("/sim/rendering/rembrandt/enabled");
-			rembrandt_node.setBoolValue(value);
-			value = getprop("/sim/current-view/deck-park");
-			deckPark_node.setBoolValue(value);
-			value = getprop("/sim/time/sun-angle-rad");
-			sunAngleRad_node.setValue(value);
+            value = getprop("/sim/rendering/rembrandt/enabled");
+            rembrandt_node.setBoolValue(value);
+            value = getprop("/sim/current-view/deck-park");
+            deckPark_node.setBoolValue(value);
+            value = getprop("/sim/time/sun-angle-rad");
+            sunAngleRad_node.setValue(value);
 
-			if (turn_old != turn){
-			turn_old = turn;
-			move_whips();
-			}
+            if (turn_old != turn){
+            turn_old = turn;
+            move_whips();
+            }
 
-			settimer(update,0);
-			}
+            settimer(update,0);
+            }
 
-			var move_whips = func {
-			var whip_pos = pos_node.getValue();
-			if (whip_pos &lt;=1 and whip_pos &gt;=0 and turn_old == 0){
+            var move_whips = func {
+            var whip_pos = pos_node.getValue();
+            if (whip_pos &lt;=1 and whip_pos &gt;=0 and turn_old == 0){
 			whip_pos += 0.001;
 
 			if (whip_pos &gt; 1)
@@ -119,13 +132,16 @@ apart from most of the very excellent textures, remain. -->
 			########
 			#start the main loop
 			update();
-
-		</load>
+        ]]>
+        </load>
 	</nasal>
 
 	<unload>
-		#print("UNLOAD Vinson ", cmdarg().getPath());
-	</unload>
+        <![CDATA[ 
+            #print("UNLOAD Vinson ", cmdarg().getPath());
+            an_spn_46_timer.stop();
+            ]]>
+    </unload>
 
 	<!-- crew to be added later
     <model>
diff --git a/Nasal/emesary.nas b/Nasal/emesary.nas
new file mode 100644
index 000000000..82ed98aa2
--- /dev/null
+++ b/Nasal/emesary.nas
@@ -0,0 +1,191 @@
+ #---------------------------------------------------------------------------
+ #
+ #	Title                : EMESARY inter-object communication
+ #
+ #	File Type            : Implementation File
+ #
+ #	Description          : Provides generic inter-object communication. For an object to receive a message it
+ #	                     : must first register with an instance of a Transmitter, and provide a Receive method
+ #
+ #	                     : To send a message use a Transmitter with an object. That's all there is to it.
+ #  
+ #  References           : http://chateau-logic.com/content/emesary-nasal-implementation-flightgear
+#                        : http://www.chateau-logic.com/content/class-based-inter-object-communication
+ #                       : http://chateau-logic.com/content/emesary-efficient-inter-object-communication-using-interfaces-and-inheritance
+ #                       : http://chateau-logic.com/content/c-wpf-application-plumbing-using-emesary
+ #
+ #	Author               : Richard Harrison (richard@zaretto.com)
+ #
+ #	Creation Date        : 29 January 2016
+ #
+ #	Version              : 4.8
+ #
+ #  Copyright � 2016 Richard Harrison           Released under GPL V2
+ #
+ #---------------------------------------------------------------------------*/
+
+# Transmitters send notifications to all recipients that are registered.
+var Transmitter =
+{
+    ReceiptStatus_OK : 0,          # Processing completed successfully
+    ReceiptStatus_Fail : 1,        # Processing resulted in at least one failure
+    ReceiptStatus_Abort : 2,       # Fatal error, stop processing any further recipieints of this message. Implicitly failed.
+    ReceiptStatus_Finished : 3,    # Definitive completion - do not send message to any further recipieints
+    ReceiptStatus_NotProcessed : 4,# Return value when method doesn't process a message.
+    ReceiptStatus_Pending : 5,     # Message sent with indeterminate return status as processing underway
+    ReceiptStatus_PendingFinished : 6,# Message definitively handled, status indeterminate. The message will not be sent any further
+
+    # create a new transmitter. shouldn't need many of these
+    new: func(_ident)
+    {
+        var new_class = { parents: [Transmitter]};
+        new_class.Recipients = [];
+        new_class.Ident = _ident;
+        return new_class;
+    },
+
+    # Add a recipient to receive notifications from this transmitter
+    Register: func (recipient)
+    {
+        append(me.Recipients, recipient);
+    },
+
+    # Stops a recipient from receiving notifications from this transmitter.
+    DeRegister: func(todelete_recipient)
+    {
+        var out_idx = 0;
+        var element_deleted = 0;
+
+        for (var idx = 0; idx < size(me.Recipients); idx += 1)
+        {
+            if (me.Recipients[idx] != todelete_recipient)
+            {
+                me.Recipients[out_idx] = me.Recipients[idx];
+                out_idx = out_idx + 1;
+            }
+            else
+                element_deleted = 1;
+        }
+
+        if (element_deleted)
+            pop(me.Recipients);
+    },
+
+    RecipientCount: func
+    {
+        return size(me.Recipients);
+    },
+
+    PrintRecipients: func
+    {
+        print("Recpient list");
+        for (var idx = 0; idx < size(me.Recipients); idx += 1)
+            print("Recpient ",idx," ",me.Recipients[idx].Ident);
+    },
+
+    # Notify all registered recipients. Stop when receipt status of abort or finished are received.
+    # The receipt status from this method will be 
+    #  - OK > message handled
+    #  - Fail > message not handled. A status of Abort from a recipient will result in our status
+    #           being fail as Abort means that the message was not and cannot be handled, and
+    #           allows for usages such as access controls.
+    NotifyAll: func(message)
+    {
+        var return_status = Transmitter.ReceiptStatus_NotProcessed;
+        foreach (var recipient; me.Recipients)
+        {
+            if (recipient.Active)
+            {
+                var rstat = recipient.Receive(message);
+
+                if(rstat == Transmitter.ReceiptStatus_Fail)
+                {
+                    return_status = Transmitter.ReceiptStatus_Fail;
+                }
+                elsif(rstat == Transmitter.ReceiptStatus_Pending)
+                {
+                    return_status = Transmitter.ReceiptStatus_Pending;
+                }
+                elsif(rstat == Transmitter.ReceiptStatus_PendingFinished)
+                {
+                    return rstat;
+                }
+#               elsif(rstat == Transmitter.ReceiptStatus_NotProcessed)
+#               {
+#                   ;
+#               }
+                elsif(rstat == Transmitter.ReceiptStatus_OK)
+                {
+                    if (return_status == Transmitter.ReceiptStatus_NotProcessed)
+                        return_status = rstat;
+                }
+                elsif(rstat == Transmitter.ReceiptStatus_Abort)
+                {
+                    return Transmitter.ReceiptStatus_Abort;
+                }
+                elsif(rstat == Transmitter.ReceiptStatus_Finished)
+                {
+                    return Transmitter.ReceiptStatus_OK;
+                }
+            }
+        }
+        return return_status;
+    },
+
+    # Returns true if a return value from NotifyAll is to be considered a failure.
+    IsFailed: func(receiptStatus)
+    {
+        # Failed is either Fail or Abort.
+        # NotProcessed isn't a failure because it hasn't been processed.
+        if (receiptStatus == Transmitter.ReceiptStatus_Fail or receiptStatus == Transmitter.ReceiptStatus_Abort)
+            return 1;
+        return 0;
+    }
+};
+
+#
+#
+# Base class for Notifications. By convention a Notification has a type and a value.
+#   SubClasses can add extra properties or methods.
+var Notification =
+{
+    new: func(_type, _value)
+    {
+        var new_class = { parents: [Notification]};
+        new_class.Value = _value;
+        new_class.Type = _type;
+        return new_class;
+    },
+};
+
+# Inherit or implement class with the same signatures to receive messages.
+var Recipient =
+{
+    new: func(_ident)
+    {
+        var new_class = { parents: [Recipient]};
+        if (_ident == nil or _ident == "")
+        {
+            _ident = id(new_class);
+            print("ERROR: Ident required when creating a recipient, defaulting to ",_ident);
+        }
+        Recipient.construct(_ident, new_class);
+    },
+    construct: func(_ident, new_class)
+    {
+        new_class.Ident = _ident;
+        new_class.Active = 1;
+        new_class.Receive = func(notification)
+        {
+            # warning if required function not 
+            print("Emesary Error: Receive function not implemented in recipient ",me.Ident);
+            return Transmitter.ReceiptStatus_NotProcessed;
+        };
+        return new_class;
+    },
+};
+
+#
+# Instantiate a Global Transmitter, this is a convenience and a known starting point. Generally most classes will
+# use this transmitters, however other transmitters can be created and merely use the global transmitter to discover each other
+var GlobalTransmitter =  Transmitter.new("GlobalTransmitter");