Fix of VNAV can not fly multiple leg.
[fg:toms-fgdata.git] / Aircraft / 777 / Nasal / AFDS.nas
1 #############################################################################
2 # 777 Autopilot Flight Director System
3 # Syd Adams
4 #
5 # speed modes: THR,THR REF, IDLE,HOLD,SPD;
6 # roll modes : TO/GA,HDG SEL,HDG HOLD, LNAV,LOC,ROLLOUT,TRK SEL, TRK HOLD,ATT;
7 # pitch modes: TO/GA,ALT,V/S,VNAV PTH,VNAV SPD,VNAV ALT,G/S,FLARE,FLCH SPD,FPA;
8 # FPA range  : -9.9 ~ 9.9 degrees
9 # VS range   : -8000 ~ 6000
10 # ALT range  : 0 ~ 50,000
11 # KIAS range : 100 ~ 399
12 # MACH range : 0.40 ~ 0.95
13 #
14 #############################################################################
15
16 #Usage : var afds = AFDS.new();
17
18 var copilot = func(msg) { setprop("/sim/messages/copilot",msg);}
19
20 var AFDS = {
21         new : func{
22                 var m = {parents:[AFDS]};
23
24                 m.spd_list=["","THR","THR REF","HOLD","IDLE","SPD"];
25
26                 m.roll_list=["","HDG SEL","HDG HOLD","LNAV","LOC","ROLLOUT",
27                 "TRK SEL","TRK HOLD","ATT","TO/GA"];
28
29                 m.pitch_list=["","ALT","V/S","VNAV PTH","VNAV SPD",
30                 "VNAV ALT","G/S","FLARE","FLCH SPD","FPA","TO/GA"];
31
32                 m.step=0;
33                 m.tiller_status = 0;
34                 m.descent_step=0;
35                 m.remaining_distance_log_last = 36000;
36                 m.heading_change_rate = 0;
37
38
39                 m.AFDS_node = props.globals.getNode("instrumentation/afds",1);
40                 m.AFDS_inputs = m.AFDS_node.getNode("inputs",1);
41                 m.AFDS_apmodes = m.AFDS_node.getNode("ap-modes",1);
42                 m.AFDS_settings = m.AFDS_node.getNode("settings",1);
43                 m.AP_settings = props.globals.getNode("autopilot/settings",1);
44
45                 m.AP = m.AFDS_inputs.initNode("AP",0,"BOOL");
46                 m.AP_disengaged = m.AFDS_inputs.initNode("AP-disengage",0,"BOOL");
47                 m.AP_passive = props.globals.initNode("autopilot/locks/passive-mode",1,"BOOL");
48                 m.AP_pitch_engaged = props.globals.initNode("autopilot/locks/pitch-engaged",1,"BOOL");
49                 m.AP_roll_engaged = props.globals.initNode("autopilot/locks/roll-engaged",1,"BOOL");
50
51                 m.FD = m.AFDS_inputs.initNode("FD",0,"BOOL");
52                 m.at1 = m.AFDS_inputs.initNode("at-armed[0]",0,"BOOL");
53                 m.at2 = m.AFDS_inputs.initNode("at-armed[1]",0,"BOOL");
54                 m.alt_knob = m.AFDS_inputs.initNode("alt-knob",0,"BOOL");
55                 m.autothrottle_mode = m.AFDS_inputs.initNode("autothrottle-index",0,"INT");
56                 m.lateral_mode = m.AFDS_inputs.initNode("lateral-index",0,"INT");
57                 m.vertical_mode = m.AFDS_inputs.initNode("vertical-index",0,"INT");
58                 m.gs_armed = m.AFDS_inputs.initNode("gs-armed",0,"BOOL");
59                 m.loc_armed = m.AFDS_inputs.initNode("loc-armed",0,"BOOL");
60                 m.vor_armed = m.AFDS_inputs.initNode("vor-armed",0,"BOOL");
61                 m.lnav_armed = m.AFDS_inputs.initNode("lnav-armed",0,"BOOL");
62                 m.vnav_armed = m.AFDS_inputs.initNode("vnav-armed",0,"BOOL");
63                 m.rollout_armed = m.AFDS_inputs.initNode("rollout-armed",0,"BOOL");
64                 m.flare_armed = m.AFDS_inputs.initNode("flare-armed",0,"BOOL");
65                 m.ias_mach_selected = m.AFDS_inputs.initNode("ias-mach-selected",0,"BOOL");
66                 m.hdg_trk_selected = m.AFDS_inputs.initNode("hdg-trk-selected",0,"BOOL");
67                 m.vs_fpa_selected = m.AFDS_inputs.initNode("vs-fpa-selected",0,"BOOL");
68                 m.bank_switch = m.AFDS_inputs.initNode("bank-limit-switch",0,"INT");
69                 m.vnav_path_mode = m.AFDS_inputs.initNode("vnav-path-mode",0,"INT");
70                 m.vnav_mcp_reset = m.AFDS_inputs.initNode("vnav-mcp-reset",0,"BOOL");
71                 m.vnav_descent = m.AFDS_inputs.initNode("vnav-descent",0,"BOOL");
72                 m.climb_continuous = m.AFDS_inputs.initNode("climb-continuous",0,"BOOL");
73                 m.indicated_vs_fpm = m.AFDS_inputs.initNode("indicated-vs-fpm",0,"DOUBLE");
74                 m.estimated_time_arrival = m.AFDS_inputs.initNode("estimated-time-arrival",0,"INT");
75                 m.remaining_distance = m.AFDS_inputs.initNode("remaining-distance",0,"DOUBLE");;
76
77                 m.ias_setting = m.AP_settings.initNode("target-speed-kt",200);# 100 - 399 #
78                 m.mach_setting = m.AP_settings.initNode("target-speed-mach",0.40);# 0.40 - 0.95 #
79                 m.vs_setting = m.AP_settings.initNode("vertical-speed-fpm",0); # -8000 to +6000 #
80                 m.hdg_setting = m.AP_settings.initNode("heading-bug-deg",360,"INT"); # 1 to 360
81                 m.hdg_setting_last = m.AP_settings.initNode("heading-bug-last",360,"INT"); # 1 to 360
82                 m.hdg_setting_active = m.AP_settings.initNode("heading-bug-active",0,"BOOL");
83                 m.trk_setting = m.AP_settings.initNode("track-bug-deg",360,"INT"); # 1 to 360
84                 m.fpa_setting = m.AP_settings.initNode("flight-path-angle",0); # -9.9 to 9.9 #
85                 m.alt_setting = m.AP_settings.initNode("counter-set-altitude-ft",10000,"DOUBLE");
86                 m.target_alt = m.AP_settings.initNode("actual-target-altitude-ft",10000,"DOUBLE");
87                 m.auto_brake_setting = m.AP_settings.initNode("autobrake",0.000,"DOUBLE");
88                 m.flare_constant_setting = m.AP_settings.initNode("flare-constant",0.000,"DOUBLE");
89                 m.thrust_lmt = m.AP_settings.initNode("thrust-lmt",1,"DOUBLE");
90                 m.flight_idle = m.AP_settings.initNode("flight-idle",0,"DOUBLE");
91
92                 m.vs_display = m.AFDS_settings.initNode("vs-display",0);
93                 m.fpa_display = m.AFDS_settings.initNode("fpa-display",0);
94                 m.bank_min = m.AFDS_settings.initNode("bank-min",-25);
95                 m.bank_max = m.AFDS_settings.initNode("bank-max",25);
96                 m.pitch_min = m.AFDS_settings.initNode("pitch-min",-10);
97                 m.pitch_max = m.AFDS_settings.initNode("pitch-max",15);
98                 m.vnav_alt = m.AFDS_settings.initNode("vnav-alt",35000);
99                 m.auto_popup = m.AFDS_settings.initNode("auto-pop-up",0,"BOOL");
100                 m.heading_magnetic = m.AFDS_settings.getNode("heading-magnetic",1);
101                 m.manual_intervention = m.AFDS_settings.initNode("manual-intervention",0,"BOOL");
102
103                 m.AP_roll_mode = m.AFDS_apmodes.initNode("roll-mode","TO/GA");
104                 m.AP_roll_arm = m.AFDS_apmodes.initNode("roll-mode-arm"," ");
105                 m.AP_pitch_mode = m.AFDS_apmodes.initNode("pitch-mode","TO/GA");
106                 m.AP_pitch_arm = m.AFDS_apmodes.initNode("pitch-mode-arm"," ");
107                 m.AP_speed_mode = m.AFDS_apmodes.initNode("speed-mode","");
108                 m.AP_annun = m.AFDS_apmodes.initNode("mode-annunciator"," ");
109
110                 m.APl = setlistener(m.AP, func m.setAP(),0,0);
111                 m.APdisl = setlistener(m.AP_disengaged, func m.setAP(),0,0);
112                 m.Lbank = setlistener(m.bank_switch, func m.setbank(),0,0);
113                 m.LTMode = setlistener(m.autothrottle_mode, func m.updateATMode(),0,0);
114                 m.WpChanged = setlistener(props.globals.getNode("/autopilot/route-manager/wp/id",1), func m.wpChanged(),0,0);
115                 m.RmDisabled = setlistener(props.globals.getNode("/autopilot/route-manager/active",1), func m.wpChanged(),0,0);
116                 return m;
117         },
118
119 ####  Inputs   ####
120 ###################
121         input : func(mode,btn)
122         {
123                 if(getprop("/systems/electrical/outputs/avionics"))
124                 {
125                         var current_alt = getprop("instrumentation/altimeter/indicated-altitude-ft");
126                         if(mode==0)
127                         {
128                                 # horizontal AP controls
129                                 if(btn == 1)            # Heading Sel button
130                                 {
131                                         if(getprop("position/gear-agl-ft") < 50)
132                                         {
133                                                 btn = me.lateral_mode.getValue();
134                                         }
135                                 }
136                                 elsif(btn == 2)         # Heading Hold button
137                                 {
138                                         # set target to current magnetic heading
139                                         var tgtHdg = int(me.heading_magnetic.getValue() + 0.50);
140                                         me.hdg_setting.setValue(tgtHdg);
141                                         me.trk_setting.setValue(tgtHdg);
142                                         if(getprop("position/gear-agl-ft") < 50)
143                                         {
144                                                 btn = me.lateral_mode.getValue();
145                                         }
146                                         else
147                                         {
148                                                 btn = 1;    # Heading sel
149                                         }
150                                 }
151                                 elsif(btn==3)           # LNAV button
152                                 {
153                                         if ((!getprop("/autopilot/route-manager/active"))or
154                                                 (getprop("/autopilot/route-manager/current-wp")<0)or
155                                                 (getprop("/autopilot/route-manager/wp/id")==""))
156                                         {
157                                                 # Oops, route manager isn't active. Keep current mode.
158                                                 btn = me.lateral_mode.getValue();
159                                                 copilot("Captain, LNAV doesn't engage. We forgot to program or activate the route manager!");
160                                         }
161                                         else
162                                         {
163                                                 if(me.lateral_mode.getValue() == 3)             # Current mode is LNAV
164                                                 {
165                                                         # set target to current magnetic heading
166                                                         var tgtHdg = int(me.heading_magnetic.getValue() + 0.50);
167                                                         me.hdg_setting.setValue(tgtHdg);
168                                                         me.trk_setting.setValue(tgtHdg);
169                                                         btn = 1;        # Heading sel
170                                                 }
171                                                 elsif(me.lnav_armed.getValue())
172                                                 {       # LNAV armed then disarm
173                                                         me.lnav_armed.setValue(0);
174                                                         btn = me.lateral_mode.getValue();
175                                                 }
176                                                 else
177                                                 {       # LNAV arm
178                                                         me.lnav_armed.setValue(1);
179                                                         btn = me.lateral_mode.getValue();
180                                                 }
181                                         }
182                                 }
183                                 me.lateral_mode.setValue(btn);
184                         }
185                         elsif(mode==1)
186                         {
187                                 # vertical AP controls
188                                 if (btn==1)
189                                 {
190                                         # hold current altitude
191                                         if(me.AP.getValue() or me.FD.getValue())
192                                         {
193                                                 var alt = int((current_alt+50)/100)*100;
194                                                 me.target_alt.setValue(alt);
195                                                 me.autothrottle_mode.setValue(5);       # A/T SPD
196                                         }
197                                         else
198                                         {
199                                                 btn = 0;
200                                         }
201                                 }
202                                 if(btn==2)
203                                 {
204                                         # hold current vertical speed
205                                         var vs = getprop("instrumentation/inst-vertical-speed-indicator/indicated-speed-fpm");
206                                         vs = int(vs/100)*100;
207                                         if (vs<-8000) vs = -8000;
208                                         if (vs>6000) vs = 6000;
209                                         me.vs_setting.setValue(vs);
210                                         if(vs == 0)
211                                         {
212                                                 me.target_alt.setValue(current_alt);
213                                         }
214                                         else
215                                         {
216                                                 me.target_alt.setValue(me.alt_setting.getValue());
217                                         }
218                                         me.autothrottle_mode.setValue(5);       # A/T SPD
219                                 }
220                                 elsif(btn == 255)
221                                 {
222                                         if(me.vs_setting.getValue() == 0)
223                                         {
224                                                 me.target_alt.setValue(current_alt);
225                                         }
226                                         else
227                                         {
228                                                 me.target_alt.setValue(me.alt_setting.getValue());
229                                         }
230                                         btn = 2;
231                                 }
232                                 if(btn==5)              # VNAV
233                                 {
234                                         if ((!getprop("/autopilot/route-manager/active"))or
235                                                 (getprop("/autopilot/route-manager/current-wp")<0)or
236                                                 (getprop("/autopilot/route-manager/wp/id")==""))
237                                         {
238                                                 # Oops, route manager isn't active. Keep current mode.
239                                                 btn = me.vertical_mode.getValue();
240                                                 copilot("Captain, VNAV doesn't engage. We forgot to program or activate the route manager!");
241                                         }
242                                         else
243                                         {
244                                                 var vnav_mode = me.vertical_mode.getValue();
245                                                 if(vnav_mode == 3)                      # Current mode is VNAV PTH
246                                                 {
247                                                 }
248                                                 elsif(vnav_mode == 4)           # Current mode is VNAV SPD
249                                                 {
250                                                 }
251                                                 elsif(vnav_mode == 5)           # Current mode is VNAV ALT
252                                                 {
253                                                 }
254                                                 elsif(me.vnav_armed.getValue())
255                                                 {       # VNAV armed then disarm
256                                                         me.vnav_armed.setValue(0);
257                                                         btn = vnav_mode;
258                                                 }
259                                                 else
260                                                 {       # VNAV arm
261                                                         me.vnav_armed.setValue(1);
262                                                         me.vnav_path_mode.setValue(0);
263                                                         me.vnav_mcp_reset.setValue(0);
264                                                         me.vnav_descent.setValue(0);
265                                                         btn = vnav_mode;
266                                                         me.descent_step = 0;
267                                                         me.manual_intervention.setValue(0);
268                                                 }
269                                         }
270                                 }
271                                 if(btn==8)              # FLCH SPD
272                                 {
273                                         # change flight level
274                                         if(((current_alt
275                                                 - getprop("autopilot/internal/airport-height")) < 400)
276                                                 or (me.at1.getValue() == 0) or (me.at2.getValue() == 0))
277                                         {
278                                                 btn = 0;
279                                         }
280                                         elsif(current_alt < me.alt_setting.getValue())
281                                         {
282                                                 me.autothrottle_mode.setValue(1);       # A/T THR
283                                         }
284                                         else
285                                         {
286                                                 me.autothrottle_mode.setValue(4);       # A/T IDLE
287                                         }
288                                         setprop("autopilot/internal/current-pitch-deg", getprop("orientation/pitch-deg"));
289                                         var alt = me.alt_setting.getValue();
290                                         me.target_alt.setValue(alt);
291                                 }
292                                 me.vertical_mode.setValue(btn);
293                         }
294                         elsif(mode == 2)
295                         {
296                                 # throttle AP controls
297                                 if(me.autothrottle_mode.getValue() != 0
298                                         or (me.at1.getValue() == 0) or (me.at2.getValue() == 0))
299                                 {
300                                         btn = 0;
301                                 }
302                                 elsif(btn == 2)         # TOGA
303                                 {
304                                         if((getprop("instrumentation/airspeed-indicator/indicated-speed-kt") > 50)
305                                                 or (getprop("/controls/flight/flaps") == 0))
306                                         {
307                                                 btn = 0;
308                                         }
309                                         me.auto_popup.setValue(1);
310                                 }
311                                 elsif((current_alt
312                                                 - getprop("autopilot/internal/airport-height")) < 400)
313                                 {
314                                         btn=0;
315                                         copilot("Captain, auto-throttle won't engage below 400ft.");
316                                 }
317                                 me.autothrottle_mode.setValue(btn);
318                         }
319                         elsif(mode==3)  #FD, LOC or G/S button
320                         {
321                                 if(btn == 2)    # FD button toggle
322                                 {
323                                         if(me.FD.getValue())
324                                         {
325                                                 if(getprop("gear/gear[1]/wow"))
326                                                 {
327                                                         me.lateral_mode.setValue(9);            # TOGA
328                                                         me.vertical_mode.setValue(10);          # TOGA
329                                                 }
330                                         }
331                                         else
332                                         {
333                                                 if(!me.AP.getValue())
334                                                 {
335                                                         me.lateral_mode.setValue(0);            # Clear
336                                                         me.vertical_mode.setValue(0);           # Clear
337                                                 }
338                                         }
339                                 }
340                                 elsif(btn == 3) # AP button toggle
341                                 {
342                                         if(!me.AP.getValue())
343                                         {
344                                                 me.rollout_armed.setValue(0);
345                                                 me.flare_armed.setValue(0);
346                                                 me.loc_armed.setValue(0);                       # Disarm
347                                                 me.gs_armed.setValue(0);                        # Disarm
348                                                 if(!me.FD.getValue())
349                                                 {
350                                                         me.lateral_mode.setValue(0);            # NO MODE
351                                                         me.vertical_mode.setValue(0);           # NO MODE
352                                                 }
353                                                 else
354                                                 {
355                                                         me.lateral_mode.setValue(2);            # HDG HOLD
356                                                         me.vertical_mode.setValue(1);           # ALT
357                                                 }
358                                         }
359                                         else
360                                         {
361                                                 if(!me.FD.getValue()
362                                                         and !me.lnav_armed.getValue()
363                                                         and (me.lateral_mode.getValue() != 3))
364                                                 {
365                                                         var current_bank = getprop("orientation/roll-deg");
366                                                         if(current_bank > 5)
367                                                         {
368                                                                 setprop("autopilot/internal/target-roll-deg", current_bank);
369                                                                 me.lateral_mode.setValue(8);            # ATT
370                                                         }
371                                                         else
372                                                         {
373                                                                 # set target to current magnetic heading
374                                                                 var tgtHdg = int(me.heading_magnetic.getValue() + 0.50);
375                                                                 me.hdg_setting.setValue(tgtHdg);
376                                                                 me.trk_setting.setValue(tgtHdg);
377                                                                 me.lateral_mode.setValue(2);            # HDG HOLD
378                                                         }
379                                                 }
380                                                 if(!me.vnav_armed.getValue()
381                                                         and (me.vertical_mode.getValue() == 0))
382                                                 {
383                                                         # hold current vertical speed
384                                                         var vs = getprop("instrumentation/inst-vertical-speed-indicator/indicated-speed-fpm");
385                                                         vs = int(vs/100)*100;
386                                                         if (vs<-8000) vs = -8000;
387                                                         if (vs>6000) vs = 6000;
388                                                         me.vs_setting.setValue(vs);
389                                                         if(vs == 0)
390                                                         {
391                                                                 me.target_alt.setValue(current_alt);
392                                                         }
393                                                         else
394                                                         {
395                                                                 me.target_alt.setValue(me.alt_setting.getValue());
396                                                         }
397                                                         me.vertical_mode.setValue(2);           # V/S
398                                                 }
399                                         }
400                                 }
401                                 else
402                                 {
403                                         if (btn==1)     #APP button
404                                         {
405                                                 var lgsmode = me.vertical_mode.getValue();
406                                                 if(lgsmode == 6)        # Already in G/S mode
407                                                 {
408                                                         me.vertical_mode.setValue(1);   # Keep current altitude
409                                                         me.gs_armed.setValue(0);                # Disarm
410                                                 }
411                                                 elsif(me.gs_armed.getValue())           # G/S armed but not captured yet
412                                                 {
413                                                         me.gs_armed.setValue(0);                # Disarm
414                                                 }
415                                                 else
416                                                 {
417                                                         me.gs_armed.setValue(1);                # G/S arm
418                                                 }
419                                         }
420                                         var llocmode = me.lateral_mode.getValue();
421                                         if(llocmode == 4)               # Alrady in LOC mode
422                                         {
423                                                 # set target to current magnetic heading
424                                                 var tgtHdg = int(me.heading_magnetic.getValue() + 0.50);
425                                                 me.hdg_setting.setValue(tgtHdg);
426                                                 me.trk_setting.setValue(tgtHdg);
427                                                 me.lateral_mode.setValue(2);            # Keep current headding
428                                                 me.loc_armed.setValue(0);                       # Disarm
429                                         }
430                                         elsif(me.loc_armed.getValue())                  # LOC armed but not captured yet
431                                         {
432                                                 if(!me.gs_armed.getValue())                     # G/S not armed
433                                                 {
434                                                         me.loc_armed.setValue(0);               # Disarm
435                                                 }
436                                         }
437                                         else
438                                         {
439                                                 me.loc_armed.setValue(1);                       # LOC arm
440                                                 me.tiller_status = getprop("/controls/gear/tiller-enabled");
441                                         }
442                                 }
443                         }
444                 }
445         },
446 ###################
447         setAP : func{
448                 var output = 1-me.AP.getValue();
449                 var disabled = me.AP_disengaged.getValue();
450                 if((output==0)and(getprop("position/gear-agl-ft")<200))
451                 {
452                         disabled = 1;
453                         copilot("Captain, autopilot won't engage below 200ft.");
454                 }
455                 if((disabled)and(output==0)){output = 1;me.AP.setValue(0);}
456                 if (output==1)
457                 {
458                         var msg="";
459                         var msg2="";
460                         var msg3="";
461                         if (abs(getprop("controls/flight/rudder-trim"))   > 0.04) msg  = "rudder";
462                         if (abs(getprop("controls/flight/elevator-trim")) > 0.04) msg2 = "pitch";
463                         if (abs(getprop("controls/flight/aileron-trim"))  > 0.04) msg3 = "aileron";
464                         if (msg ~ msg2 ~ msg3 != "")
465                         {
466                                 if ((msg != "")and(msg2!=""))
467                                         msg = msg ~ ", " ~ msg2;
468                                 else
469                                         msg = msg ~ msg2;
470                                 if ((msg != "")and(msg3!=""))
471                                         msg = msg ~ " and " ~ msg3;
472                                 else
473                                         msg = msg ~ msg3;
474                                 copilot("Captain, autopilot disengaged. Careful, check " ~ msg ~ " trim!");
475                         }
476                 }
477                 else
478                         if(me.lateral_mode.getValue() != 3) me.input(0,1);
479                 setprop("autopilot/internal/target-pitch-deg",0);
480                 setprop("autopilot/internal/target-roll-deg",0);
481                 me.AP_passive.setValue(output);
482         },
483 ###################
484         setbank : func{
485                 var banklimit = me.bank_switch.getValue();
486                 var lmt = 25;
487                 if(banklimit>0) {lmt = banklimit * 5};
488                 me.bank_max.setValue(lmt);
489                 lmt = -1 * lmt;
490                 me.bank_min.setValue(lmt);
491         },
492 ###################
493         updateATMode : func()
494         {
495                 var idx = me.autothrottle_mode.getValue();
496                 me.AP_speed_mode.setValue(me.spd_list[idx]);
497         },
498 #################
499         wpChanged : func{
500                 if (((getprop("/autopilot/route-manager/wp/id")=="")or
501                         (!getprop("/autopilot/route-manager/active")))and
502                         (me.lateral_mode.getValue() == 3)and
503                         me.AP.getValue())
504                 {
505                         # LNAV active, but route manager is disabled now => switch to HDG HOLD (current heading)
506                         me.input(0,2);
507                 }
508         },
509 #################
510         ap_update : func{
511                 var current_alt = getprop("instrumentation/altimeter/indicated-altitude-ft");
512                 var VS = getprop("velocities/vertical-speed-fps");
513                 var TAS = getprop("velocities/uBody-fps");
514                 me.indicated_vs_fpm.setValue(int((abs(VS) * 60 + 50) / 100) * 100);
515                 if(TAS < 10) TAS = 10;
516                 if(VS < -200) VS=-200;
517                 if (abs(VS/TAS)<=1)
518                 {
519                         var FPangle = math.asin(VS/TAS);
520                         FPangle *=90;
521                         setprop("autopilot/internal/fpa",FPangle);
522                 }
523                 var msg = " ";
524                 if(me.FD.getValue())
525                 {
526                         msg="FLT DIR";
527                 }
528                 if(me.AP.getValue())
529                 {
530                         msg="A/P";
531                         if(me.rollout_armed.getValue())
532                         {
533                                 msg="LAND 3";
534                         }
535                 }
536                 me.AP_annun.setValue(msg);
537                 var tmp = abs(me.vs_setting.getValue());
538                 me.vs_display.setValue(tmp);
539                 tmp = abs(me.fpa_setting.getValue());
540                 me.fpa_display.setValue(tmp);
541                 msg = "";
542                 var hdgoffset = 0;
543                 if(me.hdg_trk_selected.getValue())
544                 {
545                         hdgoffset = me.trk_setting.getValue()-getprop("orientation/heading-magnetic-deg");
546                 }
547                 else
548                 {
549                         hdgoffset = me.hdg_setting.getValue()-getprop("orientation/heading-magnetic-deg");
550                 }
551                 if(hdgoffset < -180) hdgoffset +=360;
552                 if(hdgoffset > 180) hdgoffset +=-360;
553                 setprop("autopilot/internal/fdm-heading-bug-error-deg",hdgoffset);
554
555                 if(me.step==0){ ### glideslope armed ?###
556                         msg="";
557                         if(me.gs_armed.getValue())
558                         {
559                                 msg="G/S";
560                                 var gsdefl = getprop("instrumentation/nav/gs-needle-deflection");
561                                 var gsrange = getprop("instrumentation/nav/gs-in-range");
562                                 if ((gsdefl< 0.5 and gsdefl>-0.5)and
563                                         gsrange)
564                                 {
565                                         me.vertical_mode.setValue(6);
566                                         me.gs_armed.setValue(0);
567                                 }
568                         }
569                         elsif(me.flare_armed.getValue())
570                         {
571                                 msg="FLARE";
572                         }
573                         elsif(me.vnav_armed.getValue())
574                         {
575                                 msg = "VNAV";
576                         }
577                         me.AP_pitch_arm.setValue(msg);
578
579                 }elsif(me.step==1){ ### localizer armed ? ###
580                         msg = "";
581                         if(me.loc_armed.getValue())
582                         {
583                                 msg = "LOC";
584                                 if (getprop("instrumentation/nav/in-range"))
585                                 {
586
587                                         if(!getprop("instrumentation/nav/nav-loc"))
588                                         {
589                                                 var vheading = getprop("instrumentation/nav/radials/selected-deg");
590                                                 var vvor = getprop("instrumentation/nav/heading-deg");
591                                                 var vdist = getprop("instrumentation/nav/nav-distance");
592                                                 var vorient = getprop("environment/magnetic-variation-deg");
593                                                 var vmag = getprop("orientation/heading-magnetic-deg");
594                                                 var vspeed = getprop("/instrumentation/airspeed-indicator/indicated-mach");
595                                                 var deg_to_rad = math.pi / 180;
596                                                 var vdiff = abs(vheading - vvor + vorient);
597                                                 vdiff = abs(vdist * math.sin(vdiff * deg_to_rad));
598                                                 var vlim = vspeed / 0.3 * 1300 * abs(vheading - vmag) / 45 ;
599                                                 if(vdiff < vlim)
600                                                 {
601                                                         me.lateral_mode.setValue(4);
602                                                         me.loc_armed.setValue(0);
603                                                 }
604                                         }
605                                         else
606                                         {
607                                                 var hddefl = getprop("instrumentation/nav/heading-needle-deflection");
608                                                 if(abs(hddefl) < 9.9)
609                                                 {
610                                                         me.lateral_mode.setValue(4);
611                                                         me.loc_armed.setValue(0);
612                                                         var vradials = getprop("instrumentation/nav[0]/radials/target-radial-deg")
613                                                                 - getprop("environment/magnetic-variation-deg") + 0.5;
614                                                         if(vradials < 0.5) vradials += 360;
615                                                         elsif(vradials >= 360.5) vradials -= 360;
616                                                         me.hdg_setting.setValue(vradials);
617                                                 }
618                                         }
619                                 }
620                         }
621                         elsif(me.lnav_armed.getValue())
622                         {
623                                 if(getprop("position/gear-agl-ft") > 50)
624                                 {
625                                         msg = "";
626                                         me.lnav_armed.setValue(0);              # Clear
627                                         me.lateral_mode.setValue(3);    # LNAV
628                                 }
629                                 else
630                                 {
631                                         msg = "LNAV";
632                                 }
633                         }
634                         elsif(me.rollout_armed.getValue())
635                         {
636                                 msg = "ROLLOUT";
637                         }
638                         me.AP_roll_arm.setValue(msg);
639
640                 }elsif(me.step == 2){ ### check lateral modes  ###
641                         var vheading = getprop("orientation/heading-magnetic-deg");
642                         if(vheading < 0.5)
643                         {
644                                 vheading += 360;
645                         }
646                         me.heading_magnetic.setValue(vheading);
647                         var vsethdg = me.hdg_setting.getValue();
648                         if(me.hdg_setting_last.getValue() != vsethdg)
649                         {
650                                 me.hdg_setting_last.setValue(vsethdg);
651                                 me.hdg_setting_active.setValue(1);
652                         }
653                         else
654                         {
655                                 if(me.hdg_setting_active.getValue() == 1)
656                                 {
657                                         settimer(func
658                                                 {
659                                                         if(me.hdg_setting_last.getValue() == vsethdg)
660                                                         {
661                                                                 me.hdg_setting_active.setValue(0);
662                                                         }
663
664                                                 }, 1);
665                                 }
666                         }
667                         var idx = me.lateral_mode.getValue();
668                         if ((idx == 1) or (idx == 2))
669                         {
670                                 if(getprop("position/gear-agl-ft") > 50)
671                                 {
672                                         # switch between HDG SEL to HDG HOLD
673                                         if (abs(getprop("orientation/heading-magnetic-deg")-me.hdg_setting.getValue())<2)
674                                                 idx = 2; # HDG HOLD
675                                         else
676                                                 idx = 1; # HDG SEL
677                                 }
678                         }
679                         elsif(idx == 4)         # LOC
680                         {
681                                 if((me.rollout_armed.getValue())
682                                         and (getprop("position/gear-agl-ft") < 5))
683                                 {
684                                         me.rollout_armed.setValue(0);
685                                         idx = 5;        # ROLLOUT
686                                         setprop("/controls/gear/tiller-enabled", 1);
687                                 }
688                         }
689                         elsif(idx == 5)                                                                 # ROLLOUT
690                         {
691                                 if(getprop("velocities/groundspeed-kt") < 50)
692                                 {
693                                         setprop("/controls/gear/tiller-enabled", me.tiller_status);
694                                         me.AP.setValue(0);                                              # Autopilot off
695                                         setprop("controls/flight/rudder", 0);   # Rudder set neutral
696                                         if(!me.FD.getValue())
697                                         {
698                                                 idx = 0;        # NO MODE
699                                         }
700                                         else
701                                         {
702                                                 idx = 1;        # HDG SEL
703                                         }
704                                 }
705                         }
706                         me.lateral_mode.setValue(idx);
707                         me.AP_roll_mode.setValue(me.roll_list[idx]);
708                         me.AP_roll_engaged.setBoolValue(idx > 0);
709
710                 }elsif(me.step==3){ ### check vertical modes  ###
711                         if(getprop("instrumentation/airspeed-indicator/indicated-speed-kt") < 100)
712                         {
713                                 setprop("autopilot/internal/airport-height", current_alt);
714                         }
715                         var idx = me.vertical_mode.getValue();
716                         var test_fpa = me.vs_fpa_selected.getValue();
717                         if(idx==2 and test_fpa)idx=9;
718                         if(idx==9 and !test_fpa)idx=2;
719                         if ((idx==8)or(idx==1)or(idx==2)or(idx==9)
720                                 or ((idx == 3) and (me.vnav_path_mode.getValue() == 2)))
721                         {
722                                 var offset = (abs(getprop("instrumentation/inst-vertical-speed-indicator/indicated-speed-fpm")) / 8);
723                                 if(offset < 20)
724                                 {
725                                         offset = 20;
726                                 }
727                                 # flight level change mode
728                                 if (abs(current_alt - me.alt_setting.getValue()) < offset)
729                                 {
730                                         # within MCP altitude: switch to ALT HOLD mode
731                                         if(idx != 3)
732                                         {
733                                                 idx = 1;
734                                         }
735                                         if(me.autothrottle_mode.getValue() != 0)
736                                         {
737                                                 me.autothrottle_mode.setValue(5);       # A/T SPD
738                                         }
739                                         me.vs_setting.setValue(0);
740                                         me.vnav_path_mode.setValue(0);
741                                         me.descent_step += 1;
742                                 }
743                                 if((me.mach_setting.getValue() >= 0.840)
744                                         and (me.ias_mach_selected.getValue() == 0)
745                                         and (current_alt < me.target_alt.getValue()))
746                                 {
747                                         me.ias_mach_selected.setValue(1);
748                                         me.mach_setting.setValue(0.840);
749                                 }
750                                 elsif((me.ias_setting.getValue() >= 320)
751                                         and (me.ias_mach_selected.getValue() == 1)
752                                         and (current_alt > me.target_alt.getValue()))
753                                 {
754                                         me.ias_mach_selected.setValue(0);
755                                         me.ias_setting.setValue(320);
756                                 }
757                                 # This is not official setting. Until VNAV DECENT is implemented
758                                 elsif(current_alt > me.target_alt.getValue())
759                                 {
760                                         if((current_alt < 12000)
761                                                 and (me.ias_setting.getValue() > 250))
762                                         {
763                                                 me.ias_setting.setValue(250);
764                                         }
765                                 }
766                         }
767                         elsif(idx == 3)         # VNAV PATH
768                         {
769                                 if(me.vnav_descent.getValue())
770                                 {
771                                         if(me.descent_step == 0)
772                                         {
773                                                 if(me.ias_mach_selected.getValue() == 1)
774                                                 {
775                                                         me.mach_setting.setValue(0.780);
776                                                 }
777                                                 else
778                                                 {
779                                                         me.ias_setting.setValue(280);
780                                                 }
781                                                 me.descent_step += 1;
782                                         }
783                                         elsif(me.descent_step == 1)
784                                         {
785                                                 if(me.ias_mach_selected.getValue() == 1)
786                                                 {
787                                                         if(getprop("/instrumentation/airspeed-indicator/indicated-mach") < 0.785)
788                                                         {
789                                                                 me.vnav_path_mode.setValue(1);
790                                                                 me.target_alt.setValue(me.alt_setting.getValue());
791                                                                 me.vs_setting.setValue(-2000);
792                                                                 me.descent_step += 1;
793                                                         }
794                                                 }
795                                                 else
796                                                 {
797                                                         if(getprop("/instrumentation/airspeed-indicator/indicated-speed-kt") < 285)
798                                                         {
799                                                                 me.vnav_path_mode.setValue(1);
800                                                                 me.target_alt.setValue(me.alt_setting.getValue());
801                                                                 me.vs_setting.setValue(-2000);
802                                                                 me.descent_step += 1;
803                                                         }
804                                                 }
805                                         }
806                                         elsif(me.descent_step == 2)
807                                         {
808                                                 if(me.ias_mach_selected.getValue() == 1)
809                                                 {
810                                                         if(getprop("instrumentation/airspeed-indicator/indicated-speed-kt") >= 280)
811                                                         {
812                                                                 me.ias_mach_selected.setValue(0);
813                                                                 me.ias_setting.setValue(280);
814                                                                 me.descent_step += 1;
815                                                         }
816                                                 }
817                                                 else
818                                                 {
819                                                         me.descent_step += 1;
820                                                 }
821                                         }
822                                         elsif(me.descent_step == 3)
823                                         {
824                                                 if(current_alt < 29000)
825                                                 {
826                                                         me.vnav_path_mode.setValue(2);
827                                                         me.descent_step += 1;
828                                                 }
829                                         }
830                                 }
831                                 elsif((me.mach_setting.getValue() >= 0.840)
832                                         and (me.ias_mach_selected.getValue() == 0))
833                                 {
834                                         me.ias_mach_selected.setValue(1);
835                                         me.mach_setting.setValue(0.840);
836                                 }
837                                 elsif((me.ias_setting.getValue() >= 320)
838                                         and (me.ias_mach_selected.getValue() == 1))
839                                 {
840                                         me.ias_mach_selected.setValue(0);
841                                         me.ias_setting.setValue(320);
842                                 }
843                                 elsif(me.ias_mach_selected.getValue() == 0)
844                                 {
845                                         if(current_alt < 10000)
846                                         {
847                                                 me.ias_setting.setValue(250);
848                                         }
849                                         else
850                                         {
851                                                 me.ias_setting.setValue(320);
852                                         }
853                                 }
854                                 if(me.remaining_distance.getValue() > 200)
855                                 {
856                                         var optimal_alt = ((getprop("consumables/fuel/total-fuel-lbs") + getprop("/sim/weight[0]/weight-lb") + getprop("/sim/weight[1]/weight-lb"))
857                                                                         / getprop("sim/max-payload"));
858                                         if(optimal_alt > 0.95) optimal_alt = 29000;
859                                         elsif(optimal_alt > 0.83) optimal_alt = 31000;
860                                         elsif(optimal_alt > 0.65) optimal_alt = 33000;
861                                         elsif(optimal_alt > 0.53) optimal_alt = 35000;
862                                         elsif(optimal_alt > 0.41) optimal_alt = 37000;
863                                         elsif(optimal_alt > 0.29) optimal_alt = 39000;
864                                         elsif(optimal_alt > 0.16) optimal_alt = 41000;
865                                         else optimal_alt = 43000;
866                                         if ((optimal_alt
867                                                 - me.alt_setting.getValue()) > 1000)
868                                         {
869                                                 if(getprop("autopilot/route-manager/cruise/altitude-ft") >= optimal_alt)
870                                                 {
871                                                         me.alt_setting.setValue(optimal_alt);
872                                                         idx = 4;                # VNAV SPD
873                                                         setprop("autopilot/internal/current-pitch-deg", getprop("orientation/pitch-deg"));
874                                                 }
875                                                 elsif(getprop("autopilot/route-manager/cruise/altitude-ft") > (me.alt_setting.getValue() + 500))
876                                                 {
877                                                         idx = 4;                # VNAV SPD
878                                                         setprop("autopilot/internal/current-pitch-deg", getprop("orientation/pitch-deg"));
879                                                 }
880                                         }
881                                 }
882                         }
883                         elsif(idx == 4)         # VNAV SPD
884                         {
885                                 if(getprop("/controls/flight/flaps") > 0)               # flaps down
886                                 {
887                                         me.ias_setting.setValue(getprop("instrumentation/weu/state/target-speed"));
888                                 }
889                                 elsif(current_alt < 10000)
890                                 {
891                                         me.ias_setting.setValue(250);
892                                 }
893                                 else
894                                 {
895                                         if((me.mach_setting.getValue() >= 0.840)
896                                                 and (me.ias_mach_selected.getValue() == 0)
897                                                 and (current_alt < me.target_alt.getValue()))
898                                         {
899                                                 me.ias_mach_selected.setValue(1);
900                                                 me.mach_setting.setValue(0.840);
901                                         }
902                                         elsif((me.ias_setting.getValue() >= 320)
903                                                 and (me.ias_mach_selected.getValue() == 1)
904                                                 and (current_alt > me.target_alt.getValue()))
905                                         {
906                                                 me.ias_mach_selected.setValue(0);
907                                                 me.ias_setting.setValue(320);
908                                         }
909                                         elsif(me.ias_mach_selected.getValue() == 0)
910                                         {
911                                                 if(current_alt < 10000)
912                                                 {
913                                                         me.ias_setting.setValue(250);
914                                                 }
915                                                 else
916                                                 {
917                                                         me.ias_setting.setValue(320);
918                                                 }
919                                         }
920                                 }
921                                 var optimal_alt = ((getprop("consumables/fuel/total-fuel-lbs") + getprop("/sim/weight[0]/weight-lb") + getprop("/sim/weight[1]/weight-lb"))
922                                                                 / getprop("sim/max-payload"));
923                                 if(optimal_alt > 0.95) optimal_alt = 29000;
924                                 elsif(optimal_alt > 0.83) optimal_alt = 31000;
925                                 elsif(optimal_alt > 0.65) optimal_alt = 33000;
926                                 elsif(optimal_alt > 0.53) optimal_alt = 35000;
927                                 elsif(optimal_alt > 0.41) optimal_alt = 37000;
928                                 elsif(optimal_alt > 0.29) optimal_alt = 39000;
929                                 elsif(optimal_alt > 0.16) optimal_alt = 41000;
930                                 else optimal_alt = 43000;
931                                 if(getprop("autopilot/route-manager/cruise/altitude-ft") >= optimal_alt)
932                                 {
933                                         me.alt_setting.setValue(optimal_alt);
934                                 }
935                                 else
936                                 {
937                                         me.alt_setting.setValue(getprop("autopilot/route-manager/cruise/altitude-ft"));
938                                 }
939                                 me.target_alt.setValue(me.alt_setting.getValue());
940                                 var offset = (abs(getprop("instrumentation/inst-vertical-speed-indicator/indicated-speed-fpm")) / 8);
941                                 if(offset < 20)
942                                 {
943                                         offset = 20;
944                                 }
945                                 if (abs(current_alt
946                                         - me.alt_setting.getValue()) < offset)
947                                 {
948                                         # within target altitude: switch to VANV PTH mode
949                                         idx=3;
950                                         if(me.autothrottle_mode.getValue() != 0)
951                                         {
952                                                 me.autothrottle_mode.setValue(5);       # A/T SPD
953                                         }
954                                         me.vs_setting.setValue(0);
955                                 }
956                         }
957                         elsif(idx == 6)                         # G/S
958                         {
959                                 var f_angle = getprop("autopilot/constant/flare-base") * 135 / getprop("instrumentation/airspeed-indicator/indicated-speed-kt");
960                                 me.flare_constant_setting.setValue(f_angle);
961                                 if((getprop("position/gear-agl-ft") < 50)
962                                         and (me.flare_armed.getValue()))
963                                 {
964                                         me.flare_armed.setValue(0);
965                                         idx = 7;                        # FLARE
966                                 }
967                                 elsif(me.AP.getValue() and (getprop("position/gear-agl-ft") < 1500))
968                                 {
969                                         me.rollout_armed.setValue(1);           # ROLLOUT
970                                         me.flare_armed.setValue(1);                     # FLARE
971                                         setprop("autopilot/settings/flare-speed-fps", 0);
972                                 }
973                         }
974                         elsif(idx == 7)                                                         # FLARE
975                         {
976                                 var f_angle = 0.00;
977                                 me.flare_constant_setting.setValue(f_angle);
978                                 if(me.autothrottle_mode.getValue())
979                                 {
980                                         if(getprop("position/gear-agl-ft") < 25)
981                                         {
982                                                 me.autothrottle_mode.setValue(4);       # A/T IDLE
983                                         }
984                                 }
985                                 if(getprop("velocities/groundspeed-kt") < 30)
986                                 {
987                                         if(!me.FD.getValue())
988                                         {
989                                                 idx = 0;        # NO MODE
990                                         }
991                                         else
992                                         {
993                                                 idx = 1;        # ALT
994                                         }
995                                 }
996                         }
997                         if((current_alt
998                                 - getprop("autopilot/internal/airport-height")) > 400) # Take off mode and above baro 400 ft
999                         {
1000                                 if(me.vnav_armed.getValue())
1001                                 {
1002                                         if(me.alt_setting.getValue() == int(current_alt))
1003                                         {
1004                                                 idx = 3;                # VNAV PTH
1005                                         }
1006                                         else
1007                                         {
1008                                                 idx = 4;                # VNAV SPD
1009                                         }
1010                                         me.vnav_armed.setValue(0);
1011                                 }
1012                         }
1013                         me.vertical_mode.setValue(idx);
1014                         me.AP_pitch_mode.setValue(me.pitch_list[idx]);
1015                         me.AP_pitch_engaged.setBoolValue(idx>0);
1016
1017                 }
1018                 elsif(me.step == 4)                     ### Auto Throttle mode control  ###
1019                 {
1020                         # Thrust reference rate calculation. This should be provided by FMC
1021                         var grossweight = getprop("consumables/fuel/total-fuel-lbs") + getprop("/sim/weight[0]/weight-lb") + getprop("/sim/weight[1]/weight-lb");
1022                         var derate = 0.3 - grossweight * 0.00000083;
1023                         if(me.ias_setting.getValue() < 251)
1024                         {
1025                                 var vflight_idle = (getprop("autopilot/constant/descent-profile-low-base")
1026                                         + (getprop("autopilot/constant/descent-profile-low-rate") * grossweight / 1000));
1027                         }
1028                         else
1029                         {
1030                                 var vflight_idle = (getprop("autopilot/constant/descent-profile-high-base")
1031                                         + (getprop("autopilot/constant/descent-profile-high-rate") * grossweight / 1000));
1032                         }
1033                         if(vflight_idle < 0.00) vflight_idle = 0.00;
1034                         me.flight_idle.setValue(vflight_idle);
1035                         # Thurst limit varis on altitude
1036                         var thrust_lmt = 0.96;
1037                         if(current_alt < 25000)
1038                         {
1039                                 thrust_lmt = derate / 25000 * abs(current_alt) + (0.95 - derate);
1040                         }
1041                         me.thrust_lmt.setValue(thrust_lmt);
1042                         # IAS and MACH number update in back ground
1043                         var temp = 0;
1044                         if(me.ias_mach_selected.getValue() == 1)
1045                         {
1046                                 temp = int(getprop("instrumentation/airspeed-indicator/indicated-speed-kt") + 0.5);
1047                                 me.ias_setting.setValue(temp);
1048                         }
1049                         else
1050                         {
1051                                 temp = (int(getprop("instrumentation/airspeed-indicator/indicated-mach")  * 1000 + 0.5) / 1000);
1052                                 me.mach_setting.setValue(temp);
1053                         }
1054                         # Auto throttle arm switch is offed
1055                         if((me.at1.getValue() == 0) or (me.at2.getValue() == 0))
1056                         {
1057                                 me.autothrottle_mode.setValue(0);
1058                         }
1059                         # auto-throttle disengaged when reverser is enabled
1060                         elsif (getprop("controls/engines/engine/reverser"))
1061                         {
1062                                 me.autothrottle_mode.setValue(0);
1063                         }
1064                         elsif(me.autothrottle_mode.getValue() == 2)             # THR REF
1065                         {
1066                                 if((getprop("instrumentation/airspeed-indicator/indicated-speed-kt") > 80)
1067                                         and ((current_alt - getprop("autopilot/internal/airport-height")) < 400))
1068                                 {
1069                                         me.autothrottle_mode.setValue(3);                       # HOLD
1070                                 }
1071                                 elsif((me.vertical_mode.getValue() != 3)                # not VNAV PTH
1072                                         and (me.vertical_mode.getValue() != 5))         # not VNAV ALT
1073                                 {
1074                                         if((getprop("/controls/flight/flaps") == 0)             # FLAPs up
1075                                                 and (me.vertical_mode.getValue() != 4))         # not VNAV SPD
1076                                         {
1077                                                 me.autothrottle_mode.setValue(5);               # SPD
1078                                         }
1079                                         else
1080                                         {
1081                                                 setprop("/controls/engines/engine[0]/throttle", thrust_lmt);
1082                                                 setprop("/controls/engines/engine[1]/throttle", thrust_lmt);
1083                                         }
1084                                 }
1085                         }
1086                         elsif((me.autothrottle_mode.getValue() == 4)            # Auto throttle mode IDLE 
1087                                 and ((me.vertical_mode.getValue() == 8)                 # FLCH SPD mode
1088                                         or (me.vertical_mode.getValue() == 3))          # VNAV PTH mode
1089                                 and (me.flight_idle.getValue() == getprop("/controls/engines/engine[0]/throttle"))              # #1Thrust is actual flight idle
1090                                 and (me.flight_idle.getValue() == getprop("/controls/engines/engine[1]/throttle")))             # #2Thrust is actual flight idle
1091                         {
1092                                 me.autothrottle_mode.setValue(3);                               # HOLD
1093                         }
1094                         # Take off mode and above baro 400 ft
1095                         elsif((current_alt - getprop("autopilot/internal/airport-height")) > 400)
1096                         {
1097                                 if(me.autothrottle_mode.getValue() == 1)                # THR
1098                                 {
1099                                         setprop("/controls/engines/engine[0]/throttle", thrust_lmt);
1100                                         setprop("/controls/engines/engine[1]/throttle", thrust_lmt);
1101                                 }
1102                                 elsif((me.vertical_mode.getValue() == 10)               # TO/GA
1103                                         or ((me.autothrottle_mode.getValue() == 3)      # HOLD
1104                                         and (me.vertical_mode.getValue() != 8)           # not FLCH
1105                                                 and (me.vertical_mode.getValue() != 3))) # not VNAV PTH
1106                                 {
1107                                         if(getprop("/controls/flight/flaps") == 0)
1108                                         {
1109                                                 me.autothrottle_mode.setValue(5);               # SPD
1110                                         }
1111                                         else
1112                                         {
1113                                                 me.autothrottle_mode.setValue(2);               # THR REF
1114                                         }
1115                                 }
1116                                 elsif(me.vertical_mode.getValue() == 4)                 # VNAV SPD
1117                                 {
1118                                         me.autothrottle_mode.setValue(2);                       # THR REF
1119                                 }
1120                                 elsif(me.vertical_mode.getValue() == 3)                 # VNAV PATH
1121                                 {
1122                                         if(me.vnav_path_mode.getValue() == 2)
1123                                         {
1124                                                 if(me.autothrottle_mode.getValue() != 3)
1125                                                 {
1126                                                         me.autothrottle_mode.setValue(4);       # IDLE
1127                                                 }
1128                                         }
1129                                         else
1130                                         {
1131                                                 me.autothrottle_mode.setValue(5);               # SPD
1132                                         }
1133                                 }
1134                         }
1135                         elsif((getprop("position/gear-agl-ft") > 100)           # Approach mode and above 100 ft
1136                                         and (me.vertical_mode.getValue() == 6)) 
1137                         {
1138                                 me.autothrottle_mode.setValue(5);                               # SPD
1139                         }
1140                         idx = me.autothrottle_mode.getValue();
1141                         me.AP_speed_mode.setValue(me.spd_list[idx]);
1142                 }
1143                 elsif(me.step==5)
1144                 {
1145                         if (getprop("/autopilot/route-manager/active")){
1146                                 var max_wpt = getprop("/autopilot/route-manager/route/num");
1147                                 var atm_wpt = getprop("/autopilot/route-manager/current-wp");
1148                                 var destination_elevation = getprop("/autopilot/route-manager/destination/field-elevation-ft");
1149                                 var total_distance = getprop("/autopilot/route-manager/total-distance");
1150                                 if(me.lateral_mode.getValue() == 3)             # Current mode is LNAV
1151                                 {
1152                                         if(atm_wpt < (max_wpt - 1))
1153                                         {
1154                                                 me.remaining_distance.setValue(getprop("/autopilot/route-manager/wp/remaining-distance-nm")
1155                                                         + getprop("autopilot/route-manager/wp/dist"));
1156                                                 var next_course = getprop("/autopilot/route-manager/wp[1]/bearing-deg");
1157                                         }
1158                                         else
1159                                         {
1160                                                 me.remaining_distance.setValue(getprop("autopilot/route-manager/wp/dist"));
1161                                         }
1162                                         if(me.vnav_descent.getValue() == 0)     # Calculation of Top Of Descent distance
1163                                         {
1164                                                 var top_of_descent = 16;
1165                                                 if(current_alt > 10000)
1166                                                 {
1167                                                         top_of_descent += 21;
1168                                                         if(current_alt > 29000)
1169                                                         {
1170                                                                 top_of_descent += 41.8;
1171                                                                 if(current_alt > 36000)
1172                                                                 {
1173                                                                         top_of_descent += 28;
1174                                                                         top_of_descent += (current_alt - 36000) / 1000 * 3.8;
1175                                                                 }
1176                                                                 else
1177                                                                 {
1178                                                                         top_of_descent += (current_alt - 29000) / 1000 * 4;
1179                                                                 }
1180                                                         }
1181                                                         else
1182                                                         {
1183                                                                 top_of_descent += (current_alt - 10000) / 1000 * 2.2;
1184                                                         }
1185                                                         top_of_descent += 6.7;
1186                                                 }
1187                                                 else
1188                                                 {
1189                                                         top_of_descent += (current_alt - 3000) / 1000 * 3;
1190                                                 }
1191                                                 top_of_descent -= (destination_elevation / 1000 * 3);
1192                                                 if((me.alt_setting.getValue() > 24000)
1193                                                         and (me.alt_setting.getValue() >= current_alt))
1194                                                 {
1195                                                         if(me.remaining_distance.getValue() < (top_of_descent + 10))
1196                                                         {
1197                                                                 me.vnav_mcp_reset.setValue(1);
1198                                                                 copilot("Reset MCP ALT");
1199                                                         }
1200                                                 }
1201                                                 else
1202                                                 {
1203                                                         if(me.remaining_distance.getValue() < top_of_descent)
1204                                                         {
1205                                                                 me.vnav_descent.setValue(1);
1206                                                         }
1207                                                 }
1208                                         }
1209                                 }
1210                                 if(getprop("/autopilot/route-manager/active"))
1211                                 {
1212                                         var wpt_distance = getprop("autopilot/route-manager/wp/dist");
1213                                         var groundspeed = getprop("/velocities/groundspeed-kt");
1214                                         if(wpt_distance != nil)
1215                                         {
1216                                                 var wpt_eta = (wpt_distance / groundspeed * 3600);
1217                                                 var gmt = getprop("instrumentation/clock/indicated-sec");
1218                                                 if((getprop("gear/gear[1]/wow") == 0) and (getprop("gear/gear[2]/wow") == 0))
1219                                                 {
1220                                                         gmt += (wpt_eta + 30);
1221                                                 }
1222                                                 var gmt_hour = int(gmt / 3600);
1223                                                 me.estimated_time_arrival.setValue(gmt_hour * 100 + int((gmt - gmt_hour * 3600) / 60));
1224                                                 var change_wp = abs(getprop("/autopilot/route-manager/wp[1]/bearing-deg") - me.heading_magnetic.getValue());
1225                                                 if(change_wp > 180) change_wp = (360 - change_wp);
1226                                                 if(((me.heading_change_rate * change_wp) > wpt_eta)
1227                                                         or (wpt_distance < 0.2)
1228                                                         or ((me.remaining_distance_log_last < wpt_distance) and (change_wp < 90)))
1229                                                 {
1230                                                         if (getprop("/autopilot/route-manager/current-wp") < max_wpt)
1231                                                         {
1232                                                                 atm_wpt += 1;
1233                                                                 props.globals.getNode("/autopilot/route-manager/current-wp").setValue(atm_wpt);
1234                                                                 me.remaining_distance_log_last = 36000;
1235                                                         }
1236                                                 }
1237                                                 else
1238                                                 {
1239                                                         me.remaining_distance_log_last = wpt_distance;
1240                                                 }
1241                                         }
1242                                 }
1243                         }
1244                 }elsif(me.step==6)
1245                 {
1246                         if(getprop("/controls/flight/flaps") == 0)
1247                         {
1248                                 me.auto_popup.setValue(0);
1249                         }
1250                         var ma_spd = getprop("/instrumentation/airspeed-indicator/indicated-mach");
1251                         var banklimit = getprop("/instrumentation/afds/inputs/bank-limit-switch");
1252                         if(banklimit==0)
1253                         {
1254                                 var lim = 0;
1255                                 me.heading_change_rate = 0;
1256                                 if(ma_spd > 0.85)
1257                                 {
1258                                         lim=5;
1259                                         me.heading_change_rate = 4.9 * 0.7;
1260                                 }
1261                                 elsif(ma_spd > 0.6666)
1262                                 {
1263                                         lim=10;
1264                                         me.heading_change_rate = 2.45 * 0.7;
1265                                 }
1266                                 elsif(ma_spd > 0.5)
1267                                 {
1268                                         lim=20;
1269                                         me.heading_change_rate = 1.125 * 0.7;
1270                                 }
1271                                 elsif(ma_spd > 0.3333)
1272                                 {
1273                                         lim=30;
1274                                         me.heading_change_rate = 0.625 * 0.7;
1275                                 }
1276                                 else
1277                                 {
1278                                         lim=35;
1279                                         me.heading_change_rate = 0.55 * 0.7;
1280                                 }
1281                                 props.globals.getNode("/instrumentation/afds/settings/bank-max").setValue(lim);
1282                                 lim = -1 * lim;
1283                                 props.globals.getNode("/instrumentation/afds/settings/bank-min").setValue(lim);
1284                         }
1285                 }
1286
1287                 me.step+=1;
1288                 if(me.step>6) me.step =0;
1289         },
1290 };
1291 #####################
1292
1293
1294 var afds = AFDS.new();
1295
1296 var afds_init_listener = setlistener("/sim/signals/fdm-initialized", func {
1297         removelistener(afds_init_listener);
1298         settimer(update_afds,6);
1299         print("AFDS System ... check");
1300 });
1301
1302 var update_afds = func {
1303         afds.ap_update();
1304         settimer(update_afds, 0);
1305 }