Tu-154B2 version 3.1:
[fg:toms-fgdata.git] / Aircraft / tu154b / Nasal / instruments.nas
1 #
2 # NASAL instruments for TU-154B
3 # Yurik V. Nikiforoff, yurik.nsk@gmail.com
4 # Novosibirsk, Russia
5 # jun 2007, dec 2013
6 #
7
8
9 ######################################################################
10 #
11 # Utility classes and functions.
12 #
13
14 # Before anything else change random seed.
15 srand();
16
17
18 # Chase() works like interpolate(), but tracks value changes, supports
19 # wraparound, and allows cancellation.
20 var Chase = {
21     _active: {},
22     deactivate: func(src) {
23         var m = Chase._active[src];
24         if (m != nil)
25             m.del();
26     },
27     new: func(src, dst, delay, wrap=nil) {
28         var m = {
29             parents: [Chase],
30             src: src,
31             dst: dst,
32             left: delay,
33             wrap: wrap,
34             ts: systime()
35         };
36         Chase.deactivate(src);
37         Chase._active[src] = m;
38         m.t = maketimer(0, m, Chase._update);
39         m.t.start();
40         return m;
41     },
42     active: func {
43         return (Chase._active[me.src] == me);
44     },
45     del: func {
46         Chase._active[me.src] = nil;
47         me.t.stop();
48     },
49     _update: func {
50         var ts = systime();
51         var passed = ts - me.ts;
52         var dv = (num(me.dst) == nil ? getprop(me.dst) : me.dst);
53         if (me.left > passed) {
54             var sv = getprop(me.src);
55             if (dv == nil)
56                 dv = sv;
57             var delta = dv - sv;
58             var w = (me.wrap != nil
59                      and abs(delta) > (me.wrap[1] - me.wrap[0]) / 2.0);
60             if (w) {
61                 if (sv < dv)
62                     delta -= me.wrap[1] - me.wrap[0];
63                 else
64                     delta += me.wrap[1] - me.wrap[0];
65             }
66             var nsv = sv + delta * passed / me.left;
67             if (w) {
68                 if (sv < dv)
69                     nsv += (nsv < me.wrap[0] ? me.wrap[1] : 0);
70                 else
71                     nsv -= (nsv >= me.wrap[1] ? me.wrap[1] : 0);
72             }
73             setprop(me.src, nsv);
74             me.ts = ts;
75             me.left -= passed;
76         } else {
77             setprop(me.src, dv);
78             me.t.stop();
79         }
80     }
81 };
82
83 # Smooth property re-aliasing.
84 var realias = func(src, dst, delay, wrap=nil) {
85     if (src == dst)
86         return;
87
88     var obj = props.globals.getNode(src, 1);
89     var v = getprop(src);
90     obj.unalias();
91     if (v != nil and delay > 0) {
92         setprop(src, v);
93         var c = Chase.new(src, dst, delay, wrap);
94         settimer(func {
95             if (c.active()) {
96                 c.del();
97                 if (num(dst) == nil)
98                     obj.alias(dst);
99                 else
100                     setprop(src, dst);
101             }
102         }, delay);
103     } else {
104         Chase.deactivate(src);
105         if (num(dst) == nil)
106             obj.alias(dst);
107         else
108             setprop(src, dst);
109     }
110 }
111
112 var range_wrap = func(val, min, max) {
113     while (val < min)
114         val += max - min;
115     while (val >= max)
116         val -= max - min;
117     return val;
118 }
119
120
121 ######################################################################
122 #
123 # PNP
124 #
125 # Operation:
126 #
127 # Both left and right PNPs are instances of the same pnp.xml model
128 # parameterized with corresponding properties, and behave identically.
129 # Each PNP has five modes of operation: normal (no indication), NVU
130 # (NV indication), VOR1 and VOR2 (both have VOR indication), and SP
131 # (SP indication).  Left PNP mode is selected with ABSU mode buttons
132 # (Reset and Heading buttons correspond to normal mode, Landing button
133 # corresponds to SP mode, and the rest button correspondence is
134 # one-to-one).  Right PNP mode is selected with the dedicated switch
135 # on PN-6.
136 #
137 # In all modes of PNP operation left handle sets heading (yellow
138 # rotating marks) and right handle sets course in degrees (shown with
139 # digit wheels in the top right corner of PNP).  In all modes but NVU
140 # course needle also points to the dialed course.  In NVU mode course
141 # needle points to current NVU course from active V-140 set.
142 #
143 # Course deflection needle in VOR1 or VOR2 mode shows offset in
144 # degrees of the VOR radial selected on corresponding KURS-MP up to 10
145 # degrees at full scale.  In SP mode it shows offset in degrees of the
146 # ILS-LOC radial (again, up to 10 degrees; ILS frequency is set in
147 # left KURS-MP set). In NVU mode the needle shows Z offset of NVU
148 # course in km up to 4 km at full scale (that is, negated Z value from
149 # active NVU counter clipped to 4 km).  In normal mode (or when
150 # there's no VOR or ILS-LOC in range) the needle is not deflected and
151 # course blanker is shown.
152 #
153 # Glideslope deflection needle in SP mode shows offset in degrees to
154 # the ILS-GS up to 0.7 degrees at full scale (ILS frequency is set in
155 # left KURS-MP set).  In other modes (or when there's no ILS-GS in
156 # range) the needle is not deflected and glideslope blanker is shown.
157 #
158 # Note that VOR1 and SP modes are mutually exclusive: when you tune
159 # left KURS-MP to VOR then PNP in SP mode will be blanked on both
160 # channels.  Likewise, when you tune left KURS-MP to ILS then PNP in
161 # VOR1 mode will be blanked on both channels.  Also note that tuning
162 # right KURS-MP to ILS will result in VOR2 mode blanked on both
163 # channels.
164 #
165 # When /tu154/instrumentation/distance-to-pnp is set to true distance
166 # digit wheels show abs(S) from active NVU block.
167 #
168 #
169 # Implementation:
170 #
171 # With setlistener() we track changes to all properties that determine
172 # PNP mode and blankers (but not needle input values).  When any such
173 # change occurs we recompute PNP mode, set blankers accordingly, and
174 # alias() PNP needle properties to relevant inputs so that needle
175 # value updates happen implicitly after that.  This way we track only
176 # infrequent changes (like button presses or switch toggling), but do
177 # not have to recompute needle values every frame.
178 #
179
180 var pnp_mode_update = func(i, mode) {
181     var plane = "/tu154/instrumentation/pnp["~i~"]/plane-dialed";
182     var defl_course = 0;
183     var defl_gs = 0;
184     var distance = getprop("/tu154/instrumentation/pnp["~i~"]/distance");
185     var blank_course = 1;
186     var blank_gs = 1;
187     var blank_dist = 1;
188     if (mode == 1 and getprop("fdm/jsbsim/instrumentation/nvu/active")) { # NVU
189         plane = "fdm/jsbsim/instrumentation/nvu/ZPU-active";
190         defl_course = "fdm/jsbsim/instrumentation/nvu/Z-deflection";
191         blank_course = 0;
192     } else if (mode == 2 and !getprop("instrumentation/nav[0]/nav-loc")) { #VOR1
193         if (getprop("instrumentation/nav[0]/in-range")) {
194             defl_course =
195                 "instrumentation/nav[0]/heading-needle-deflection-norm";
196             blank_course = 0;
197         }
198     } else if (mode == 3 and !getprop("instrumentation/nav[1]/nav-loc")) { #VOR2
199         if (getprop("instrumentation/nav[1]/in-range")) {
200             defl_course =
201                 "instrumentation/nav[1]/heading-needle-deflection-norm";
202             blank_course = 0;
203         }
204     } else if (mode == 4 and getprop("instrumentation/nav[0]/nav-loc")) { # SP
205         if (getprop("instrumentation/nav[0]/in-range")) {
206             defl_course =
207                 "instrumentation/nav[0]/heading-needle-deflection-norm";
208             blank_course = 0;
209         }
210         if (getprop("instrumentation/nav[0]/gs-in-range")) {
211             defl_gs = "instrumentation/nav[0]/gs-needle-deflection-norm";
212             blank_gs = 0;
213         }
214     }
215     if (getprop("tu154/instrumentation/distance-to-pnp")
216         and getprop("fdm/jsbsim/instrumentation/nvu/active")) {
217         distance = "fdm/jsbsim/instrumentation/nvu/S-active";
218         blank_dist = 0;
219     }
220     setprop("tu154/instrumentation/pnp["~i~"]/mode", mode);
221     realias("/tu154/instrumentation/pnp["~i~"]/plane-deg", plane, 0.5,
222             [0, 360]);
223     realias("/tu154/instrumentation/pnp["~i~"]/defl-course", defl_course, 0.5);
224     realias("/tu154/instrumentation/pnp["~i~"]/defl-gs", defl_gs, 0.5);
225     realias("/tu154/instrumentation/pnp["~i~"]/distance", distance, 0.5);
226     setprop("tu154/instrumentation/pnp["~i~"]/blank-course", blank_course);
227     setprop("tu154/instrumentation/pnp["~i~"]/blank-gs", blank_gs);
228     setprop("tu154/instrumentation/pnp["~i~"]/blank-dist", blank_dist);
229 }
230
231 # PNP mode for first pilot.
232 var pnp0_mode_update = func {
233     var sel = getprop("fdm/jsbsim/ap/roll-selector") or 0;
234     if (!getprop("instrumentation/heading-indicator[0]/serviceable")
235         or !getprop("tu154/systems/absu/serviceable"))
236         sel = -1;
237
238     var mode = 0; # Disabled or Stab or ZK (sel == 0 or sel == 1 or sel == 2)
239     if (sel == 3) { # VOR
240         mode = 2;
241         if (getprop("tu154/instrumentation/pn-5/az-2"))
242             mode = 3;
243     } else if (sel == 4) { # NVU
244         mode = 1;
245     } else if (sel == 5) { # SP
246         mode = 4;
247     } else if (sel != -1) {
248         if (getprop("tu154/switches/pn-5-navigac") == 0
249             and getprop("tu154/switches/pn-5-posadk") == 1
250             and getprop("instrumentation/nav[0]/nav-loc")
251             and (getprop("instrumentation/nav[0]/in-range")
252                  or getprop("instrumentation/nav[0]/gs-in-range")))
253             mode = 4;
254     }
255     pnp_mode_update(0, mode);
256 }
257
258 # PNP mode for second pilot.
259 var pnp1_mode_update = func {
260     var sel = getprop("tu154/switches/pn-6-selector") or 0;
261     if (!getprop("instrumentation/heading-indicator[1]/serviceable"))
262         sel = 0;
263     pnp_mode_update(1, sel);
264 }
265
266 var pnp_both_mode_update = func {
267     pnp0_mode_update();
268     pnp1_mode_update();
269 }
270
271 setlistener("tu154/systems/absu/serviceable", pnp0_mode_update, 0, 0);
272 setlistener("tu154/switches/pn-5-navigac", pnp0_mode_update);
273 setlistener("tu154/switches/pn-5-posadk", pnp0_mode_update);
274 setlistener("fdm/jsbsim/ap/roll-selector", pnp0_mode_update);
275 setlistener("instrumentation/heading-indicator[0]/serviceable",
276             pnp0_mode_update, 1, 0);
277
278 setlistener("tu154/switches/pn-6-selector", pnp1_mode_update);
279 setlistener("instrumentation/heading-indicator[1]/serviceable",
280             pnp1_mode_update, 1, 0);
281
282 setlistener("fdm/jsbsim/instrumentation/nvu/active", pnp_both_mode_update, 0, 0);
283 setlistener("tu154/instrumentation/distance-to-pnp", pnp_both_mode_update);
284 setlistener("instrumentation/nav[0]/nav-loc", pnp_both_mode_update, 0, 0);
285 setlistener("instrumentation/nav[1]/nav-loc", pnp_both_mode_update, 0, 0);
286 setlistener("instrumentation/nav[0]/in-range", pnp_both_mode_update, 0, 0);
287 setlistener("instrumentation/nav[1]/in-range", pnp_both_mode_update, 0, 0);
288 setlistener("instrumentation/nav[0]/gs-in-range", pnp_both_mode_update, 0, 0);
289
290
291 ######################################################################
292 #
293 # DME
294 #
295
296 # Smooth DME updates.
297 var dme_distance = func(i) {
298     var distance = getprop("instrumentation/dme["~i~"]/indicated-distance-nm");
299     # We ignore exact zero distance because it signifies out of range
300     # condition, and we want to keep last value in this case.  Within DME
301     # proximity exact zero distance is highly unlikely, and close to zero
302     # update will be enough.
303     if (distance) {
304         distance = int(distance * 18.52) * 100;
305         interpolate("tu154/instrumentation/dme["~i~"]/distance", distance, 0.2);
306     }
307 }
308 setlistener("instrumentation/dme[0]/indicated-distance-nm",
309             func { dme_distance(0) }, 0, 0);
310 setlistener("instrumentation/dme[1]/indicated-distance-nm",
311             func { dme_distance(1) }, 0, 0);
312 setlistener("instrumentation/dme[2]/indicated-distance-nm",
313             func { dme_distance(2) }, 0, 0);
314
315
316 # Added by Yurik dec 2013
317 setprop("instrumentation/dme[0]/frequencies/selected-mhz", 
318   getprop("instrumentation/nav[0]/frequencies/selected-mhz") );
319
320 setprop("instrumentation/dme[1]/frequencies/selected-mhz", 
321   getprop("instrumentation/nav[1]/frequencies/selected-mhz") );
322
323 ######################################################################
324 #
325 # IDR-1
326 #
327 # Implementation:
328 #
329 # Note that DME cannel in VOR-DME and ILS-DME operates in the same way
330 # so IDR-1 works with both.
331 #
332
333 var idr_mode_update = func(i, selector) {
334     var sel = getprop(selector);
335     if (int(sel) != sel) # The switch is in transition.
336         return;
337     var ni = (sel ? 3 - sel : 0); # 2 -> 1, 1 -> 2, 0 -> 0
338     var distance = getprop("/tu154/instrumentation/idr-1["~i~"]/distance");
339     var blank = 1;
340     if (getprop("instrumentation/dme["~ni~"]/in-range")) {
341         distance = "tu154/instrumentation/dme["~ni~"]/distance";
342         blank = 0;
343     }
344     realias("/tu154/instrumentation/idr-1["~i~"]/distance", distance, 0.5);
345     setprop("tu154/instrumentation/idr-1["~i~"]/blank", blank);
346 }
347
348 var idr0_mode_update = func {
349     idr_mode_update(0, "tu154/switches/capt-idr-selector");
350 }
351
352 var idr1_mode_update = func {
353     idr_mode_update(1, "tu154/switches/copilot-idr-selector");
354 }
355
356 var idr_both_mode_update = func {
357     idr0_mode_update();
358     idr1_mode_update();
359 }
360
361 setlistener("tu154/switches/capt-idr-selector", idr0_mode_update, 1);
362
363 setlistener("tu154/switches/copilot-idr-selector", idr1_mode_update, 1);
364
365 setlistener("instrumentation/dme[0]/in-range", idr_both_mode_update, 0, 0);
366 setlistener("instrumentation/dme[1]/in-range", idr_both_mode_update, 0, 0);
367 setlistener("instrumentation/dme[2]/in-range", idr_both_mode_update, 0, 0);
368
369
370 ######################################################################
371 #
372 # RV-5M
373 #
374
375 var rv_altitude_update = func {
376     var alt_m = getprop("position/altitude-agl-ft") * 0.3048;
377     settimer(rv_altitude_update, (alt_m < 1200 ? 0.1 : (alt_m - 900) / 300));
378     if (alt_m > 0) {
379         var pitch_deg = getprop("orientation/pitch-deg");
380         var roll_deg = getprop("orientation/roll-deg");
381         if (-90 < pitch_deg and pitch_deg < 90
382             and -90 < roll_deg and roll_deg < 90) {
383             var beam_rad = math.acos(math.cos(pitch_deg / 57.3)
384                                      * math.cos(roll_deg / 57.3));
385             if (beam_rad > 0.262) { # > 15 degrees
386                 beam_rad -= 0.262;
387                 alt_m /= math.cos(beam_rad);
388             }
389             if (alt_m > 850)
390                 alt_m = 850;
391         } else {
392             alt_m = 850;
393         }
394     } else {
395         alt_m = 0;
396     }
397     setprop("fdm/jsbsim/instrumentation/indicated-altitude-m", alt_m);
398 }
399 rv_altitude_update();
400
401 var rv_mode_update = func(i, toggled) {
402     # Temporal hack to wait electrical initialization.
403     if (getprop("tu154/switches/main-battery") == nil) {
404         settimer(func { rv_mode_update(i, 1) }, 0.5);
405         return;
406     }
407
408     if (i == 0) {
409         var ac_obj = electrical.AC3x200_bus_1L;
410         var volts = "tu154/systems/electrical/buses/AC3x200-bus-1L/volts";
411     } else {
412         var ac_obj = electrical.AC3x200_bus_3R;
413         var volts = "tu154/systems/electrical/buses/AC3x200-bus-3L/volts";
414     }
415     volts = getprop(volts) or 0;
416     var powered = (volts > 150.0);
417     var altitude = "tu154/instrumentation/rv-5m["~i~"]/altitude";
418     var switch = "RV-5-"~(i + 1);
419     var warn = 0;
420     var blank = 1;
421     if (powered and getprop("tu154/switches/"~switch)) {
422         if (toggled) {
423             ac_obj.add_output(switch, 10.0);
424             realias(altitude, 850, 3);
425             settimer(func {
426                 realias(altitude,
427                         "fdm/jsbsim/instrumentation/indicated-altitude-m", 3);
428                 settimer(func { rv_mode_update(i, 0) }, 3);
429             }, 15); # Up to 2 minutes in reality.
430         } else {
431             warn = (getprop(altitude) <=
432                     getprop("tu154/instrumentation/rv-5m["~i~"]/dialed"));
433             blank = 0;
434             var agl = getprop("position/altitude-agl-ft");
435             if (agl < 4000) { # < ~1200m
436                 settimer(func { rv_mode_update(i, 0) }, 0.1);
437             } else {
438                 # FIXME: RV should be switched off, but for now we have
439                 # to track power state.
440                 settimer(func { rv_mode_update(i, 0) }, 0.5);
441             }
442         }
443     } else {
444         if (!toggled) {
445             ac_obj.rm_output(switch);
446             realias(altitude, 0, 3);
447         }
448         settimer(func { rv_mode_update(i, 1) }, 0.5);
449     }
450
451     setprop("tu154/instrumentation/rv-5m["~i~"]/warn", warn);
452     setprop("tu154/instrumentation/rv-5m["~i~"]/blank", blank);
453 }
454
455 rv_mode_update(0, 1);
456 rv_mode_update(1, 1);
457
458
459 ######################################################################
460 #
461 # IKU-1
462 #
463
464 var iku_vor_bearing = func(i) {
465     setprop("tu154/instrumentation/nav["~i~"]/bearing-deg",
466             getprop("instrumentation/nav["~i~"]/radials/reciprocal-radial-deg")
467             - getprop("fdm/jsbsim/instrumentation/bgmk-"~(i+1)));
468 }
469 var iku_vor_bearing_timer = [maketimer(0.1, func { iku_vor_bearing(0) }),
470                              maketimer(0.1, func { iku_vor_bearing(1) })];
471
472 var iku_mode_update = func(i, b) {
473     var sel = getprop("tu154/instrumentation/iku-1["~i~"]/mode-"~b);
474     var bearing = 90;
475     var j = b - 1;
476     if (sel) {
477         if (getprop("instrumentation/nav["~j~"]/in-range")
478             and !getprop("instrumentation/nav["~j~"]/nav-loc")) {
479             iku_vor_bearing_timer[j].start();
480             bearing = "tu154/instrumentation/nav["~j~"]/bearing-deg";
481         } else {
482             iku_vor_bearing_timer[j].stop();
483         }
484     } else {
485         iku_vor_bearing_timer[j].stop();
486         if (getprop("instrumentation/adf["~j~"]/in-range"))
487             bearing = "instrumentation/adf["~j~"]/indicated-bearing-deg";
488     }
489
490     interpolate("tu154/instrumentation/iku-1["~i~"]/trans-"~b, sel, 0.1);
491     realias("tu154/instrumentation/iku-1["~i~"]/heading-"~b, bearing, 0.5,
492             [0, 360]);
493 }
494
495 var iku0_mode1_update = func {
496     iku_mode_update(0, 1);
497 }
498
499 var iku0_mode2_update = func {
500     iku_mode_update(0, 2);
501 }
502
503 var iku1_mode1_update = func {
504     iku_mode_update(1, 1);
505 }
506
507 var iku1_mode2_update = func {
508     iku_mode_update(1, 2);
509 }
510
511 var iku_both_mode1_update = func {
512     iku0_mode1_update();
513     iku1_mode1_update();
514 }
515
516 var iku_both_mode2_update = func {
517     iku0_mode2_update();
518     iku1_mode2_update();
519 }
520
521 setlistener("instrumentation/adf[0]/in-range", iku_both_mode1_update, 0, 0);
522 setlistener("instrumentation/nav[0]/in-range", iku_both_mode1_update, 0, 0);
523 setlistener("instrumentation/nav[0]/nav-loc", iku_both_mode1_update, 0, 0);
524 setlistener("instrumentation/adf[1]/in-range", iku_both_mode2_update, 0, 0);
525 setlistener("instrumentation/nav[1]/in-range", iku_both_mode2_update, 0, 0);
526 setlistener("instrumentation/nav[1]/nav-loc", iku_both_mode2_update, 0, 0);
527 setlistener("tu154/instrumentation/iku-1[0]/mode-1", iku0_mode1_update, 1);
528 setlistener("tu154/instrumentation/iku-1[0]/mode-2", iku0_mode2_update, 1);
529 setlistener("tu154/instrumentation/iku-1[1]/mode-1", iku1_mode1_update, 1);
530 setlistener("tu154/instrumentation/iku-1[1]/mode-2", iku1_mode2_update, 1);
531
532
533 ######################################################################
534 #
535 # UShDB
536 #
537
538 var ushdb_mode_update = func(b) {
539     var sel = getprop("tu154/switches/ushdb-sel-"~b);
540     if (int(sel) != sel) # The switch is in transition.
541         return;
542     var bearing = 90;
543     var j = b - 1;
544     if (sel) {
545         if (getprop("instrumentation/nav["~j~"]/in-range")
546             and !getprop("instrumentation/nav["~j~"]/nav-loc"))
547             bearing =
548                 "instrumentation/nav["~j~"]/radials/reciprocal-radial-deg";
549     } else {
550         if (getprop("instrumentation/adf["~j~"]/in-range"))
551             bearing = "instrumentation/adf["~j~"]/indicated-bearing-deg";
552     }
553
554     realias("tu154/instrumentation/ushdb/heading-deg-"~b, bearing, 0.5,
555             [0, 360]);
556 }
557
558 var ushdb_mode1_update = func {
559     ushdb_mode_update(1);
560 }
561
562 var ushdb_mode2_update = func {
563     ushdb_mode_update(2);
564 }
565
566 setlistener("instrumentation/adf[0]/in-range", ushdb_mode1_update, 0, 0);
567 setlistener("instrumentation/nav[0]/in-range", ushdb_mode1_update, 0, 0);
568 setlistener("instrumentation/nav[0]/nav-loc", ushdb_mode1_update, 0, 0);
569 setlistener("instrumentation/adf[1]/in-range", ushdb_mode2_update, 0, 0);
570 setlistener("instrumentation/nav[1]/in-range", ushdb_mode2_update, 0, 0);
571 setlistener("instrumentation/nav[1]/nav-loc", ushdb_mode2_update, 0, 0);
572 setlistener("tu154/switches/ushdb-sel-1", ushdb_mode1_update, 1);
573 setlistener("tu154/switches/ushdb-sel-2", ushdb_mode2_update, 1);
574
575
576 ######################################################################
577 #
578 # UVID
579 #
580
581 var uvid_inhg = func(i) {
582     var inhgX100 = getprop("tu154/instrumentation/altimeter["~i~"]/inhgX100");
583     setprop("instrumentation/altimeter["~i~"]/setting-inhg", inhgX100 / 100.0);
584
585     if (i == 0)
586         setprop("tu154/instrumentation/altimeter[0]/mmhg", inhgX100 * 0.254);
587
588     if (getprop("tu154/instrumentation/altimeters-sync-inhg")) {
589         setprop("tu154/instrumentation/altimeter["~(1-i)~"]/inhgX100",
590                 inhgX100);
591     }
592 }
593
594 setlistener("tu154/instrumentation/altimeter[0]/inhgX100",
595             func { uvid_inhg(0) }, 1, 0);
596 setlistener("tu154/instrumentation/altimeter[1]/inhgX100",
597             func { uvid_inhg(1) }, 1, 0);
598
599
600 ######################################################################
601 #
602 # RSBN & PPDA
603 #
604 # Implementation note:
605 #
606 # instrumentation/nav doesn't export true radial value, only twisted
607 # one.  Instead of computing true azimuth in Nasal we remember twist
608 # value (which is zero for RSBN but non-zero for VOR) and alias to
609 # twisted radial.  rsbn_corr() is sill called every 0.1 second, but
610 # only when correction is enabled.
611 #
612
613 var rsbn_corr = func {
614     var twist = getprop("tu154/instrumentation/rsbn/twist");
615     var ds = (getprop("fdm/jsbsim/instrumentation/nvu/S-active")
616               - getprop("fdm/jsbsim/instrumentation/nvu/Spm-active"));
617     var dz = (getprop("fdm/jsbsim/instrumentation/nvu/Z-active")
618               - getprop("fdm/jsbsim/instrumentation/nvu/Zpm-active"));
619     if (!getprop("instrumentation/nav[2]/nav-loc")
620         and getprop("instrumentation/nav[2]/in-range")
621         and getprop("instrumentation/dme[2]/in-range")) {
622         setprop("tu154/systems/electrical/indicators/nvu-correction-on", 1);
623
624         var radial = getprop("tu154/instrumentation/rsbn/radial") + twist;
625         var distance = getprop("tu154/instrumentation/rsbn/distance");
626         var uk = (getprop("tu154/instrumentation/b-8m/outer")
627                   + getprop("tu154/instrumentation/b-8m/inner") / 10);
628         var angle_rad = (radial - uk) / 57.295779;
629         var deltaS = distance * math.cos(angle_rad) - ds;
630         var deltaZ = distance * math.sin(angle_rad) - dz;
631
632         var Sb = getprop("fdm/jsbsim/instrumentation/nvu/S-base-active");
633         var Zb = getprop("fdm/jsbsim/instrumentation/nvu/Z-base-active");
634         interpolate("fdm/jsbsim/instrumentation/nvu/S-base-active", Sb + deltaS,
635                     (abs(deltaS) + 40000) / 40000);
636         interpolate("fdm/jsbsim/instrumentation/nvu/Z-base-active", Zb + deltaZ,
637                     (abs(deltaZ) + 40000) / 40000);
638     } else {
639         setprop("tu154/systems/electrical/indicators/nvu-correction-on", 0);
640
641         var tks = getprop("fdm/jsbsim/instrumentation/tks-consumers") or 0;
642         var zpu_true =
643             (getprop("fdm/jsbsim/instrumentation/nvu/ZPU-active")
644              - getprop("instrumentation/heading-indicator["~tks~"]/offset-deg"));
645         var deg = (ds or dz ? math.atan2(-dz, -ds) * 57.3 : 0);
646         var radial = range_wrap(deg - zpu_true - twist, 0, 360);
647         var distance = math.sqrt(ds * ds + dz * dz);
648         distance = int(distance / 100) * 100;
649
650         setprop("tu154/instrumentation/rsbn/radial-auto", radial);
651         if (getprop("tu154/instrumentation/rsbn/distance-target") != distance) {
652             setprop("tu154/instrumentation/rsbn/distance-target", distance);
653             interpolate("tu154/instrumentation/rsbn/distance-auto", distance,
654                         0.2);
655         }
656     }
657 }
658 var rsbn_corr_timer = maketimer(0.1, rsbn_corr);
659
660 var ppda_mode_update = func {
661     var radial = getprop("tu154/instrumentation/rsbn/radial");
662     var distance = getprop("tu154/instrumentation/rsbn/distance");
663     var nav_in_range = 1;
664     var dme_in_range = 1;
665     var twist = 0;
666
667     rsbn_corr_timer.stop();
668     setprop("tu154/systems/electrical/indicators/nvu-correction-on", 0);
669     if (getprop("tu154/instrumentation/rsbn/serviceable")) {
670         if (!getprop("instrumentation/nav[2]/nav-loc")) {
671            nav_in_range = getprop("instrumentation/nav[2]/in-range");
672            dme_in_range = getprop("instrumentation/dme[2]/in-range");
673         }
674         if (nav_in_range) {
675             radial = "instrumentation/nav[2]/radials/actual-deg";
676             twist = getprop("instrumentation/nav[2]/radials/target-radial-deg");
677         }
678         if (dme_in_range) {
679             distance = "tu154/instrumentation/dme[2]/distance";
680         }
681         if (getprop("fdm/jsbsim/instrumentation/nvu/active")
682             and getprop("tu154/switches/v-51-corr") == 1) {
683             if (!nav_in_range)
684                 radial = "tu154/instrumentation/rsbn/radial-auto";
685             if (!dme_in_range)
686                 distance = "tu154/instrumentation/rsbn/distance-auto";
687             rsbn_corr_timer.start();
688         }
689     }
690
691     interpolate("tu154/instrumentation/rsbn/twist", twist, 0.5);
692     realias("/tu154/instrumentation/rsbn/radial", radial, 0.5, [0, 360]);
693     realias("/tu154/instrumentation/rsbn/distance", distance, 0.5);
694     setprop("tu154/systems/electrical/indicators/azimuth-avton", !nav_in_range);
695     setprop("tu154/systems/electrical/indicators/range-avton", !dme_in_range);
696 }
697
698 setlistener("tu154/instrumentation/rsbn/serviceable", ppda_mode_update, 1, 0);
699 setlistener("instrumentation/nav[2]/nav-loc", ppda_mode_update, 0, 0);
700 setlistener("instrumentation/nav[2]/in-range", ppda_mode_update, 0, 0);
701 setlistener("instrumentation/dme[2]/in-range", ppda_mode_update, 0, 0);
702 setlistener("fdm/jsbsim/instrumentation/nvu/active", ppda_mode_update, 0, 0);
703 setlistener("tu154/switches/v-51-corr", ppda_mode_update, 0, 0);
704
705
706 ######################################################################
707 #
708 # USVP & DISS
709 #
710
711 var usvp_mode_update = func {
712     var target = "fdm/jsbsim/instrumentation/svs/TAS-fps";
713     if (getprop("tu154/switches/usvp-selector"))
714         target = "fdm/jsbsim/instrumentation/nvu/GS-fps";
715
716     var mode_out = getprop("fdm/jsbsim/instrumentation/nvu/mode-out");
717     setprop("fdm/jsbsim/instrumentation/nvu/mode-in", mode_out);
718     realias("tu154/instrumentation/usvp/speed-fps", target, 0.5);
719
720     var diss_memory =
721         (mode_out != 2
722          and getprop("fdm/jsbsim/instrumentation/nvu/source") == 2
723          and getprop("fdm/jsbsim/instrumentation/diss/sensitivity") > 0);
724     setprop("tu154/systems/electrical/indicators/memory-diss",
725             (diss_memory ? 1 : 0));
726 }
727
728 setlistener("tu154/switches/usvp-selector", usvp_mode_update, 1, 0);
729 setlistener("fdm/jsbsim/instrumentation/nvu/mode-out", usvp_mode_update, 0, 0);
730 setlistener("fdm/jsbsim/instrumentation/nvu/source", usvp_mode_update, 0, 0);
731 setlistener("fdm/jsbsim/instrumentation/diss/sensitivity", usvp_mode_update,
732             0, 0);
733 setlistener("fdm/jsbsim/instrumentation/svs/serviceable", usvp_mode_update,
734             0, 0);
735
736 setlistener("tu154/systems/svs/powered", func {
737     setprop("fdm/jsbsim/instrumentation/svs/serviceable",
738             getprop("tu154/systems/svs/powered"));
739 }, 0, 0);
740
741 var diss_sensitivity_update = func {
742     var diss_terrain = getprop("tu154/switches/DISS-surface");
743     var lat = getprop("position/latitude-deg");
744     var lon = getprop("position/longitude-deg");
745     # Probe terrain below aircraft and in ~6 km vicinity.
746     var info = geodinfo(lat, lon);
747     var above_ground = (info != nil and info[1] != nil and info[1].solid);
748     for (var i = 0; i < 3 and !above_ground; i += 1) {
749         info = geodinfo(lat + 0.1 * (rand() - 0.5), lon + 0.1 * (rand() - 0.5));
750         above_ground = (info != nil and info[1] != nil and info[1].solid);
751     }
752     var sensitivity = 1; # Threshold is >= 0.2
753     if (above_ground) {
754         if (!diss_terrain)
755             sensitivity = rand() * 0.5; # >= 0.2 with probability 0.6.
756     } else {
757         # Beaufort scale 1 corresponds to 3 kts wind, and this
758         # corresponds to wave amplitude of 1.06.
759         var wave_amp = getprop("environment/wave/amp");
760         sensitivity = (wave_amp - 1) * 3.3333;
761         if (diss_terrain)
762             sensitivity *= rand() * 0.2857; # >= 0.2 with probability 0.3.
763     }
764     setprop("fdm/jsbsim/instrumentation/diss/sensitivity", sensitivity or 0.001);
765 }
766 var diss_sensitivity_update_timer = maketimer(60, diss_sensitivity_update);
767
768 setlistener("tu154/switches/DISS-surface", func {
769     if (getprop("tu154/instrumentation/diss/powered"))
770         diss_sensitivity_update_timer.restart(60);
771 }, 0, 0);
772
773 setlistener("tu154/instrumentation/diss/powered", func {
774     var powered = getprop("tu154/instrumentation/diss/powered");
775     if (powered) {
776         diss_sensitivity_update_timer.start();
777         electrical.AC3x200_bus_1L.add_output("DISS", 25);
778     } else {
779         diss_sensitivity_update_timer.stop();
780         setprop("fdm/jsbsim/instrumentation/diss/sensitivity", 0);
781         electrical.AC3x200_bus_1L.rm_output("DISS");
782     }
783 }, 0, 0);
784
785
786 ######################################################################
787 #
788 # NVU
789 #
790 # Implementation: the basic idea is simple: in Systems/nvu.xml we
791 # compute S,Z-active and S,Z-inactive, and here we play with aliases
792 # to swap active and inactive NVU blocks.  Smooth movement of digit
793 # wheels is implemented in Systems/property-filters.xml.
794 #
795
796 var nvu_swap_alias = func(active, name) {
797     var inactive = 3 - active;
798     var src = "tu154/systems/nvu/"~name;
799     var dst = "fdm/jsbsim/instrumentation/nvu/"~name;
800     var av = getprop(dst~"-active");
801     var iv = getprop(dst~"-inactive");
802     setprop(dst~"-active", iv);
803     setprop(dst~"-inactive", av);
804     realias(src~"-"~active, dst~"-active", 0);
805     realias(src~"-"~inactive, dst~"-inactive", 0);
806     if (name == "S" or name == "Z") {
807         var I = getprop("fdm/jsbsim/instrumentation/nvu/"~name~"-integrator");
808         setprop("fdm/jsbsim/instrumentation/nvu/"~name~"-base-active", iv - I);
809     }
810 }
811
812 nvu_swap_alias(1, "S");
813 nvu_swap_alias(1, "Z");
814 nvu_swap_alias(1, "Spm");
815 nvu_swap_alias(1, "Zpm");
816 nvu_swap_alias(1, "ZPU");
817
818 var nvu_enable = func {
819     var powered = getprop("tu154/systems/nvu/powered");
820     setprop("fdm/jsbsim/instrumentation/nvu/active", powered);
821     if (powered)
822         electrical.AC3x200_bus_1L.add_output("NVU", 150);
823     else
824         electrical.AC3x200_bus_1L.rm_output("NVU");
825 }
826
827 setlistener("tu154/systems/nvu/powered", nvu_enable, 0, 0);
828
829 var nvu_virtual_navigator_load = func(li, lin) {
830     var active = getprop("fdm/jsbsim/instrumentation/nvu/active") or 1;
831     var inactive = 3 - active;
832     var msg = "";
833     var route = props.globals.getNode("tu154/systems/nvu-calc/route", 1);
834
835     var leg = route.getChild("leg", li);
836     if (leg != nil) {
837         var values = leg.getValues();
838         msg = sprintf("Virtual navigator: on leg %s - %s (%.1f km)",
839                       values.from, values.to, -values.S);
840
841         var beacon = route.getChild("beacon", li);
842         if (beacon != nil) {
843            var b = beacon.getValues();
844            setprop("fdm/jsbsim/instrumentation/nvu/Spm-active", b.S * 1000);
845            setprop("fdm/jsbsim/instrumentation/nvu/Zpm-active", b.Z * 1000);
846            var UK_outer = int(b.UK / 10) * 10;
847            var UK_inner = (b.UK - UK_outer) * 10;
848            realias("tu154/instrumentation/b-8m/outer", UK_outer, 3);
849            realias("tu154/instrumentation/b-8m/inner", UK_inner, 3);
850            msg ~= sprintf(", beacon %s (%s %.2f mhz)", b.name, b.ident, b.freq);
851         }
852     }
853
854     var leg2 = route.getChild("leg", lin);
855     if (leg2 != nil) {
856         var values = leg2.getValues();
857         var ZPU = int(values.ZPU * 10 + 0.5) / 10;
858         setprop("fdm/jsbsim/instrumentation/nvu/Spm-inactive", values.S * 1000);
859         setprop("fdm/jsbsim/instrumentation/nvu/Zpm-inactive", 0);
860         setprop("fdm/jsbsim/instrumentation/nvu/ZPU-inactive", ZPU);
861     } else {
862         msg ~= " - last leg";
863         if (getprop("tu154/switches/v-51-selector-2") > 0) {
864            setprop("tu154/switches/v-51-selector-2", 0);
865            msg ~= ", disabling LUR";
866         }
867     }
868
869     if (leg != nil)
870        help.messenger(msg);
871 }
872
873 var nvu_set_integrator = func(name, i, val) {
874     var I = getprop("fdm/jsbsim/instrumentation/nvu/"~name~"-integrator");
875     setprop("fdm/jsbsim/instrumentation/nvu/"~name~"-base-active", val - I);
876 }
877
878 var nvu_calculator_load = func {
879     var active = getprop("fdm/jsbsim/instrumentation/nvu/active");
880     if (!active)
881         return;
882
883     var route = props.globals.getNode("tu154/systems/nvu-calc/route", 1);
884     var lin = getprop("tu154/systems/nvu/leg-next");
885     var leg = route.getChild("leg", lin);
886     if (leg == nil)
887         return;
888
889     if (getprop("fdm/jsbsim/instrumentation/nvu/stopped")) {
890         var values = leg.getValues();
891         var ZPU = int(values.ZPU * 10 + 0.5) / 10;
892         nvu_set_integrator("S", active, values.S * 1000);
893         nvu_set_integrator("Z", active, 0);
894         setprop("fdm/jsbsim/instrumentation/nvu/ZPU-active", ZPU);
895         setprop("tu154/systems/nvu/leg", lin);
896         lin += 1;
897         setprop("tu154/systems/nvu/leg-next", lin);
898     }
899
900     nvu_virtual_navigator_load(getprop("tu154/systems/nvu/leg"), lin);
901 }
902
903 var nvu_zpu_adjust_sign = 0;
904 var nvu_zpu_adjust = func(vi, sign) {
905     var active = getprop("fdm/jsbsim/instrumentation/nvu/active");
906     if (!active)
907         return;
908
909     var ZPU = getprop("tu154/systems/nvu/ZPU-"~vi);
910     var step = getprop("tu154/instrumentation/v-140/adjust-step-"~vi);
911     if (!sign) {
912         ZPU = getprop("tu154/systems/nvu/ZPU-"~vi~"-smooth");
913         if (nvu_zpu_adjust_sign > 0)
914             ZPU = math.ceil(ZPU * 10 + 0.025) / 10;
915         else
916             ZPU = math.floor(ZPU * 10 + 0.025) / 10;
917     }
918     ZPU = range_wrap(int((ZPU + sign * step + 360) * 10 + 0.5) / 10, 0, 360);
919
920     setprop("tu154/systems/nvu/ZPU-"~vi, ZPU);
921
922     nvu_zpu_adjust_sign = sign;
923 }
924
925 var nvu_distance_adjust = func(sign) {
926     var active = getprop("fdm/jsbsim/instrumentation/nvu/active");
927     if (!active)
928         return;
929
930     var sel = getprop("tu154/switches/v-51-selector-1");
931     if (!sel)
932         return;
933
934     var name = [
935         "Z-base-active",
936         "S-base-active",
937         "Zpm-active",
938         "Spm-active",
939         "",
940         "Spm-inactive",
941         "Zpm-inactive",
942         "S-base-active",
943         "Z-base-active"
944     ][sel + 4];
945
946     var prop = "fdm/jsbsim/instrumentation/nvu/"~name;
947     var v = getprop(prop);
948     if (sign) {
949         var speed = (getprop("tu154/instrumentation/v-51/adjust-speed")
950                      / getprop("tu154/instrumentation/v-51/scale"));
951         interpolate(prop, v + sign * speed * 610, 610);
952     } else {
953         interpolate(prop, v, 0);
954     }
955 }
956
957 var nvu_next_leg = func {
958     var active = getprop("fdm/jsbsim/instrumentation/nvu/active");
959     if (!active)
960         return;
961
962     var active = 3 - active;
963
964     setprop("fdm/jsbsim/instrumentation/nvu/active", active);
965
966     nvu_swap_alias(active, "S");
967     nvu_swap_alias(active, "Z");
968     nvu_swap_alias(active, "Spm");
969     nvu_swap_alias(active, "Zpm");
970     nvu_swap_alias(active, "ZPU");
971
972     var lin = getprop("tu154/systems/nvu/leg-next");
973     setprop("tu154/systems/nvu/leg", lin);
974     setprop("tu154/systems/nvu/leg-next", lin + 1);
975     if (getprop("tu154/systems/nvu-calc/virtual-navigator")) {
976         nvu_virtual_navigator_load(lin, lin + 1);
977     }
978 }
979
980 setlistener("tu154/switches/v-51-selector-2", func {
981     var sel = getprop("tu154/switches/v-51-selector-2");
982     if (sel == -1)
983         nvu_next_leg();
984 }, 0, 0);
985
986 var nvu_fork_apply = func {
987     if (getprop("/tu154/systems/nvu-calc/fork-only-route"))
988        return;
989
990     var fork = getprop("tu154/systems/nvu-calc/fork") or 0;
991     if (!getprop("tu154/systems/nvu-calc/fork-applied"))
992         fork = -fork;
993
994     var val = getprop("instrumentation/heading-indicator[0]/offset-deg");
995     setprop("instrumentation/heading-indicator[0]/offset-deg",
996             range_wrap(val + fork, 0, 360));
997
998     val = getprop("instrumentation/heading-indicator[1]/offset-deg");
999     setprop("instrumentation/heading-indicator[1]/offset-deg",
1000             range_wrap(val + fork, 0, 360));
1001
1002     val = getprop("fdm/jsbsim/instrumentation/nvu/ZPU-active");
1003     val = range_wrap(val + fork, 0, 360);
1004     setprop("fdm/jsbsim/instrumentation/nvu/ZPU-active", val);
1005
1006     val = getprop("fdm/jsbsim/instrumentation/nvu/ZPU-inactive");
1007     val = range_wrap(val + fork, 0, 360);
1008     setprop("fdm/jsbsim/instrumentation/nvu/ZPU-inactive", val);
1009
1010     var mode = getprop("fdm/jsbsim/instrumentation/nvu/mode-out");
1011     if (mode == 3 or mode == 0) {
1012         val = getprop("fdm/jsbsim/instrumentation/nvu/wind-azimuth-svs");
1013         val = range_wrap(val + fork, 0, 360);
1014         setprop("fdm/jsbsim/instrumentation/nvu/wind-azimuth-svs", val);
1015     }
1016 }
1017
1018 setlistener("tu154/systems/nvu-calc/fork-applied", nvu_fork_apply, 0, 0);
1019
1020 var nvu_lur_vicinity = func {
1021     var sel = getprop("tu154/switches/v-51-selector-2");
1022     var active = (getprop("fdm/jsbsim/instrumentation/nvu/active")
1023                   and getprop("fdm/jsbsim/instrumentation/nvu/LUR-vicinity-out")
1024                   and sel > 0);
1025     var S = getprop("fdm/jsbsim/instrumentation/nvu/S-active");
1026     var LUR = sel * 5000;
1027     if (!active or (-LUR <= S and S <= LUR)) {
1028         setprop("tu154/systems/electrical/indicators/change-waypoint", 0);
1029         if (active)
1030             nvu_next_leg();
1031     } else {
1032         setprop("tu154/systems/electrical/indicators/change-waypoint", 1);
1033         settimer(nvu_lur_vicinity, 0);
1034     }
1035 }
1036
1037 setlistener("fdm/jsbsim/instrumentation/nvu/LUR-vicinity-out", func {
1038     if (getprop("fdm/jsbsim/instrumentation/nvu/LUR-vicinity-out"))
1039         nvu_lur_vicinity();
1040 }, 0, 0);
1041
1042
1043 ######################################################################
1044 #
1045 # V-57
1046 #
1047
1048 var nvu_wind_mode_update = func {
1049     var target = "diss";
1050     var mode = getprop("fdm/jsbsim/instrumentation/nvu/mode-out");
1051     if (mode == 3 or mode == 0) {
1052         setprop("fdm/jsbsim/instrumentation/nvu/wind-speed-svs",
1053                 getprop("tu154/systems/nvu/wind-speed"));
1054         setprop("fdm/jsbsim/instrumentation/nvu/wind-azimuth-svs",
1055                 getprop("tu154/systems/nvu/wind-azimuth"));
1056         target = "svs";
1057     }
1058
1059     realias("tu154/systems/nvu/wind-speed",
1060             "fdm/jsbsim/instrumentation/nvu/wind-speed-"~target, 0);
1061     realias("tu154/systems/nvu/wind-azimuth",
1062             "fdm/jsbsim/instrumentation/nvu/wind-azimuth-"~target, 0);
1063 }
1064
1065 setlistener("fdm/jsbsim/instrumentation/nvu/mode-out", nvu_wind_mode_update,
1066             1, 0);
1067
1068 var nvu_wind_adjust_sign = 0;
1069 var nvu_wind_adjust = func(which, sign) {
1070     var mode = getprop("fdm/jsbsim/instrumentation/nvu/mode-out");
1071     if (mode != 3
1072         and (mode != 0 or !getprop("fdm/jsbsim/instrumentation/nvu/active")))
1073         return;
1074
1075     var step = getprop("tu154/instrumentation/v-57/"~which~"-adjust-step");
1076
1077     var v = getprop("fdm/jsbsim/instrumentation/nvu/wind-"~which~"-svs");
1078     if (!sign) {
1079         v = getprop("tu154/systems/nvu/wind-"~which~"-smooth");
1080         if (nvu_wind_adjust_sign > 0)
1081             v = math.ceil(v * 4 + 0.0625) / 4;
1082         else
1083             v = math.floor(v * 4 + 0.0625) / 4;
1084     }
1085     v += sign * step;
1086     if (which == "speed") {
1087         if (v < 0)
1088             v = 0;
1089         else if (v > 999)
1090             v = 999;
1091     }
1092
1093     setprop("fdm/jsbsim/instrumentation/nvu/wind-"~which~"-svs", v);
1094
1095     nvu_wind_adjust_sign = sign;
1096 }
1097
1098
1099 ######################################################################
1100
1101 svs_power = func{
1102 if( getprop( "tu154/switches/SVS-power" ) == 1.0 )
1103         electrical.AC3x200_bus_1L.add_output( "SVS", 10.0);
1104 else electrical.AC3x200_bus_1L.rm_output( "SVS" );
1105 }
1106
1107 setlistener("tu154/switches/SVS-power", svs_power, 0, 0);
1108
1109 # feet
1110 uvid15_power = func{
1111 if( getprop( "tu154/switches/UVID" ) == 1.0 )
1112         electrical.AC3x200_bus_1L.add_output( "UVID-15", 10.0);
1113 else electrical.AC3x200_bus_1L.rm_output( "UVID-15" );
1114 }
1115
1116 setlistener("tu154/switches/UVID", uvid15_power, 0, 0 );
1117
1118
1119 # SKAWK support
1120
1121 var skawk_handler = func{
1122   var digit_1 = getprop( "tu154/instrumentation/skawk/handle-1" );
1123   var digit_2 = getprop( "tu154/instrumentation/skawk/handle-2" );
1124   var digit_3 = getprop( "tu154/instrumentation/skawk/handle-3" );
1125   var digit_4 = getprop( "tu154/instrumentation/skawk/handle-4" );
1126   var mode_handle = getprop("tu154/instrumentation/skawk/handle-5" );
1127   var mode = 1;
1128
1129   if( mode_handle == 0 ) mode = 4;      # A mode
1130   if( mode_handle == 2 ) mode = 5;      # C mode
1131   if( mode_handle == 1 ) mode = 1;      # Standby mode (B)
1132   if( mode_handle == 3 ) mode = 3;      # Ground mode (D)
1133
1134   setprop("instrumentation/transponder/inputs/knob-mode", mode );
1135   setprop("instrumentation/transponder/inputs/digit[3]", digit_1 );
1136   setprop("instrumentation/transponder/inputs/digit[2]", digit_2 );
1137   setprop("instrumentation/transponder/inputs/digit[1]", digit_3 );
1138   setprop("instrumentation/transponder/inputs/digit", digit_4 );
1139 }
1140
1141 # Load defaults at startup
1142 var skawk_init = func{
1143 setprop( "tu154/instrumentation/skawk/handle-1", getprop( "instrumentation/transponder/inputs/digit[3]" ) );
1144 setprop( "tu154/instrumentation/skawk/handle-2", getprop( "instrumentation/transponder/inputs/digit[2]" ) );
1145 setprop( "tu154/instrumentation/skawk/handle-3", getprop( "instrumentation/transponder/inputs/digit[1]" ) );
1146 setprop( "tu154/instrumentation/skawk/handle-4", getprop( "instrumentation/transponder/inputs/digit" ) );
1147 setprop( "tu154/instrumentation/skawk/handle-5", 1 );
1148 setprop( "instrumentation/transponder/inputs/knob-mode", 1 );
1149
1150 setlistener("tu154/instrumentation/skawk/handle-1", skawk_handler,0,0 );
1151 setlistener("tu154/instrumentation/skawk/handle-2", skawk_handler,0,0 );
1152 setlistener("tu154/instrumentation/skawk/handle-3", skawk_handler,0,0 );
1153 setlistener("tu154/instrumentation/skawk/handle-4", skawk_handler,0,0 );
1154 setlistener("tu154/instrumentation/skawk/handle-5", skawk_handler,0,0 );
1155 }
1156
1157 # We use transponder for FG 2.10 and newest
1158
1159 if( getprop( "instrumentation/transponder/inputs/digit" ) != nil ) skawk_init();
1160
1161
1162 # BKK support
1163
1164 bkk_handler = func{
1165 settimer( bkk_handler, 0.5 );
1166 var param = getprop("tu154/instrumentation/bkk/serviceable");
1167 if( param == nil ) return;
1168 if( param == 0 )
1169         {
1170         setprop("tu154/instrumentation/bkk/mgv-1-failure", 1.0);
1171         setprop("tu154/instrumentation/bkk/mgv-2-failure", 1.0);
1172         setprop("tu154/instrumentation/bkk/mgv-contr-failure", 1.0);
1173
1174         var lamp_pwr = getprop("tu154/systems/electrical/buses/DC27-bus-L/volts");
1175         if( lamp_pwr == nil ) lamp_pwr = 0.0;
1176         if( lamp_pwr > 0 ) lamp_pwr = 1.0;
1177         setprop("tu154/systems/electrical/indicators/contr-gyro", lamp_pwr );
1178         setprop("tu154/systems/electrical/indicators/mgvk-failure", lamp_pwr);
1179         return;
1180         }
1181 # check MGV
1182 # Get MGV data
1183 var mgv_1_pitch = getprop("instrumentation/attitude-indicator[0]/indicated-pitch-deg");
1184 if( mgv_1_pitch == nil ) return;
1185 var mgv_1_roll = getprop("instrumentation/attitude-indicator[0]/indicated-roll-deg");
1186 if( mgv_1_roll  == nil ) return;
1187 var mgv_2_pitch = getprop("instrumentation/attitude-indicator[1]/indicated-pitch-deg");
1188 if( mgv_2_pitch  == nil ) return;
1189 var mgv_2_roll = getprop("instrumentation/attitude-indicator[1]/indicated-roll-deg");
1190 if( mgv_2_roll  == nil ) return;
1191 var mgv_c_pitch = getprop("instrumentation/attitude-indicator[2]/indicated-pitch-deg");
1192 if( mgv_c_pitch  == nil ) return;
1193 var mgv_c_roll = getprop("instrumentation/attitude-indicator[2]/indicated-roll-deg");
1194 if( mgv_c_roll  == nil ) return;
1195 var delta = getprop("tu154/instrumentation/bkk/delta-deg");
1196
1197 # check MGV-1
1198 if( delta < abs( mgv_1_pitch - mgv_c_pitch ) )
1199         setprop("tu154/instrumentation/bkk/mgv-1-failure", 1);
1200 if( delta < abs( mgv_1_roll - mgv_c_roll ) )
1201         setprop("tu154/instrumentation/bkk/mgv-1-failure", 1);
1202
1203 # check MGV-2   
1204 if( delta < abs( mgv_2_pitch - mgv_c_pitch ) )
1205         setprop("tu154/instrumentation/bkk/mgv-2-failure", 1);
1206 if( delta < abs( mgv_2_roll - mgv_c_roll ) )
1207         setprop("tu154/instrumentation/bkk/mgv-2-failure", 1);
1208
1209 # check MGV-contr               
1210 if( getprop("tu154/instrumentation/bkk/mgv-1-failure" ) == 1 ){
1211         if( getprop("tu154/instrumentation/bkk/mgv-2-failure" ) == 1 )
1212                 {
1213                 setprop("tu154/instrumentation/bkk/mgv-contr-failure", 1);
1214                 setprop("tu154/systems/electrical/indicators/contr-gyro", 1);
1215                 setprop("tu154/systems/electrical/indicators/mgvk-failure", 1);
1216 }}
1217                 
1218 # Check roll limit
1219
1220 var ias = getprop( "instrumentation/airspeed-indicator/indicated-speed-kt" );
1221 if( ias == nil ) ias = 0.0;
1222 ias = ias * 1.852; # to kmh
1223 var alt = getprop( "instrumentation/altimeter/indicated-altitude-ft" );
1224 if( alt == nil ) alt = 0.0;
1225 alt = alt * 0.3048; # to m
1226 var limit = 15.0;
1227 if( getprop( "tu154/switches/pn-5-posadk" ) == 1 ){
1228         if( alt >= 250.0 ) limit = 33.0;        
1229         if( alt < 250.0 ) limit = 15.0;
1230         }
1231 else {
1232         if( ias > 340.0 ) limit = 33.0; 
1233         if( alt < 280.0 ) limit = 15.0;
1234
1235         }
1236
1237 if( getprop("tu154/instrumentation/bkk/mgv-1-failure" == 0 ) ){
1238         if( abs( mgv_1_roll ) > limit ){
1239                 if( mgv_1_roll < 0 ){
1240                 setprop("tu154/systems/electrical/indicators/left-bank", 1); }
1241                 else { setprop("tu154/systems/electrical/indicators/right-bank", 1); }
1242                 }
1243         if( abs( mgv_1_roll ) < limit ) {
1244                 if( mgv_1_roll < 0 ){
1245                 setprop("tu154/systems/electrical/indicators/left-bank", 0); }
1246                 else { setprop("tu154/systems/electrical/indicators/right-bank", 0); }
1247                 }
1248         }
1249 else    {
1250 if( getprop("tu154/instrumentation/bkk/mgv-2-failure" ) == 0 )
1251         if( abs( mgv_2_roll ) > limit ){
1252                 if( mgv_2_roll < 0 ){
1253                 setprop("tu154/systems/electrical/indicators/left-bank", 1); }
1254                 else { setprop("tu154/systems/electrical/indicators/right-bank", 1); }
1255                 }
1256         if( abs( mgv_1_roll ) < limit ) {
1257                 if( mgv_2_roll < 0 ){
1258                 setprop("tu154/systems/electrical/indicators/left-bank", 0); }
1259                 else { setprop("tu154/systems/electrical/indicators/right-bank", 0); }
1260                 }
1261         }
1262 }
1263
1264
1265
1266 bkk_adjust = func{
1267
1268         var param = getprop("tu154/systems/mgv/one");
1269         if( param == nil ) return;
1270         param = param + 0.1;
1271         if( param >= 6.0 ) param = 6.0; 
1272         setprop("tu154/systems/mgv/one", param);
1273         
1274         param = getprop("tu154/systems/mgv/two");
1275         if( param == nil ) return;
1276         param = param + 0.1;
1277         if( param >= 6.0 ) param = 6.0; 
1278         setprop("tu154/systems/mgv/two", param);
1279         
1280         param = getprop("tu154/systems/mgv/contr");
1281         if( param == nil ) return;
1282         param = param + 0.1;
1283         if( param >= 6.0 ) param = 6.0; 
1284         setprop("tu154/systems/mgv/contr", param);
1285                 
1286 }
1287
1288 bkk_shutdown = func{
1289 if ( arg[0] == 0 ) 
1290         {
1291 #       setprop( "instrumentation/attitude-indicator[0]/serviceable", 0 );
1292         setprop("tu154/systems/mgv/one", 0.0);
1293 #setprop( "instrumentation/attitude-indicator[0]/internal-pitch-deg",-rand()*30.0 );
1294 #setprop( "instrumentation/attitude-indicator[0]/internal-roll-deg", -rand()*15.0 );
1295         }
1296 if ( arg[0] == 1 ) 
1297         {
1298 #       setprop( "instrumentation/attitude-indicator[1]/serviceable", 0 );
1299         setprop("tu154/systems/mgv/two", 0.0);
1300 #setprop( "instrumentation/attitude-indicator[1]/internal-pitch-deg",-rand()*30.0 );
1301 #setprop( "instrumentation/attitude-indicator[1]/internal-roll-deg", -rand()*15.0 );
1302         }
1303 if ( arg[0] == 2 ) 
1304         {
1305         setprop( "instrumentation/attitude-indicator[2]/serviceable", 0 );
1306         setprop("tu154/systems/mgv/contr", 0.0);
1307 #setprop( "instrumentation/attitude-indicator[2]/internal-pitch-deg",-rand()*30.0 );
1308 #setprop( "instrumentation/attitude-indicator[2]/internal-roll-deg", -rand()*15.0 );
1309         }
1310 if ( arg[0] == 3 ) 
1311         {
1312         setprop( "instrumentation/attitude-indicator[3]/serviceable", 0 );
1313 #setprop( "instrumentation/attitude-indicator[3]/internal-pitch-deg",-rand()*30.0 );
1314 #setprop( "instrumentation/attitude-indicator[3]/internal-roll-deg", -rand()*15.0 );
1315         }
1316
1317         
1318
1319 }
1320
1321 bkk_reset = func(i) {
1322 setprop("tu154/instrumentation/bkk/mgv-"~i~"-failure", 0);
1323 setprop("tu154/instrumentation/bkk/mgv-contr-failure", 0);
1324 setprop("tu154/systems/electrical/indicators/contr-gyro", 0);
1325 setprop("tu154/systems/electrical/indicators/mgvk-failure", 0);
1326 }
1327
1328
1329
1330 bkk_handler();
1331
1332 # BKK power support
1333 bkk_power = func{
1334 if( getprop( "tu154/switches/BKK-power" ) == 1.0 )
1335         electrical.AC3x200_bus_1L.add_output( "BKK", 25.0);
1336 else electrical.AC3x200_bus_1L.rm_output( "BKK" );
1337 }
1338
1339 setlistener("tu154/switches/BKK-power", bkk_power,0,0);
1340
1341 # AGR power support
1342 agr_power = func{
1343 if( getprop( "tu154/switches/AGR" ) == 1.0 )
1344         electrical.AC3x200_bus_1L.add_output( "AGR", 10.0);
1345 else electrical.AC3x200_bus_1L.rm_output( "AGR" );
1346 }
1347 # MGV-1 power support
1348 mgv_1_power = func{
1349 if( getprop( "tu154/switches/PKP-left" ) == 1.0 )
1350         electrical.AC3x200_bus_1L.add_output( "MGV-1", 10.0);
1351 else electrical.AC3x200_bus_1L.rm_output( "MGV-1" );
1352 }
1353 # MGV-2 power support
1354 mgv_2_power = func{
1355 if( getprop( "tu154/switches/PKP-right" ) == 1.0 )
1356         electrical.AC3x200_bus_3R.add_output( "MGV-2", 10.0);
1357 else electrical.AC3x200_bus_3R.rm_output( "MGV-2" );
1358 }
1359 # MGV contr power support
1360 mgv_c_power = func{
1361 if( getprop( "tu154/switches/MGV-contr" ) == 1.0 )
1362         electrical.AC3x200_bus_3R.add_output( "MGV-contr", 10.0);
1363 else electrical.AC3x200_bus_3R.rm_output( "MGV-contr" );
1364 }
1365
1366 setlistener("tu154/switches/AGR", agr_power,0,0);
1367 setlistener("tu154/switches/PKP-left", mgv_1_power,0,0);
1368 setlistener("tu154/switches/PKP-right", mgv_2_power,0,0);
1369 setlistener("tu154/switches/MGV-contr", mgv_c_power,0,0);
1370
1371
1372 # ************************* TKS staff ***********************************
1373
1374 # auto corrector for GA-3 and BGMK
1375 var tks_corr = func{
1376 var mk1 = getprop("fdm/jsbsim/instrumentation/km-5-1");
1377 if( mk1 == nil ) return;
1378 var mk2 = getprop("fdm/jsbsim/instrumentation/km-5-2");
1379 if( mk2 == nil ) return;
1380 help.tks();     # show help string
1381 if( getprop("tu154/switches/pu-11-gpk") == 1 ) { # GA-3 correction
1382 # parameters GA-3
1383    var gpk_1 = getprop("fdm/jsbsim/instrumentation/ga3-corrected-1");
1384    var gpk_2 = getprop("fdm/jsbsim/instrumentation/ga3-corrected-2");
1385    if( gpk_1 == nil ) return;
1386    if( gpk_2 == nil ) return;
1387    if( getprop("tu154/switches/pu-11-corr") == 0 ) # kontr
1388         {
1389         if( getprop("instrumentation/heading-indicator[1]/serviceable" ) != 1 ) return;
1390         var delta = gpk_2 - mk2;
1391         if( abs( delta ) < 0.5 ) return;                # not adjust small values
1392         if( delta > 360.0 ) delta = delta - 360.0;      # bias control
1393         if( delta < 0.0 ) delta = delta + 360.0;
1394         if( delta > 180 ) delta = 0.5; else delta = -0.5;# find short way       
1395         var offset = getprop("instrumentation/heading-indicator[1]/offset-deg");
1396         if( offset == nil ) return;
1397         setprop("instrumentation/heading-indicator[1]/offset-deg", offset+delta );
1398         return;
1399         }
1400 else    { # osn
1401         if( getprop("instrumentation/heading-indicator[0]/serviceable" ) != 1 ) return;
1402         var delta = gpk_1 - mk1;
1403         if( abs( delta ) < 1.0 ) return;                # not adjust small values
1404         if( delta > 360.0 ) delta = delta - 360.0;      # bias control
1405         if( delta < 0.0 ) delta = delta + 360.0;
1406         if( delta > 180 ) delta = 0.5; else delta = -0.5;# find short way       
1407         var offset = getprop("instrumentation/heading-indicator[0]/offset-deg");
1408         if( offset == nil ) return;
1409         setprop("instrumentation/heading-indicator[0]/offset-deg", offset+delta );
1410         return;
1411         }
1412    } # end GA-3 correction
1413    if( getprop("tu154/switches/pu-11-gpk") == 0 ) { # BGMK correction
1414 # parameters BGMK
1415    if( getprop("tu154/switches/pu-11-corr") == 0 ) # BGMK-2
1416         {
1417         setprop("fdm/jsbsim/instrumentation/bgmk-corrector-2",1);
1418         }
1419 else    { # BGMK-1
1420         setprop("fdm/jsbsim/instrumentation/bgmk-corrector-1",1);
1421         } 
1422    } # end BGMK correction
1423 }
1424
1425 # manually adjust gyro heading - GA-3 only
1426 tks_adj = func{
1427 if( getprop("tu154/switches/pu-11-gpk") != 0 ) return;
1428 help.tks();     # show help string
1429 var delta = 0.1;
1430 if( getprop("tu154/switches/pu-11-corr") == 0 ) # kontr
1431         {
1432         if( getprop("instrumentation/heading-indicator[1]/serviceable" ) != 1 ) return;
1433         if( arg[0] == 1 ) # to right
1434                 {
1435                 var offset = getprop("instrumentation/heading-indicator[1]/offset-deg");
1436                 if( offset == nil ) return;
1437                 setprop("instrumentation/heading-indicator[1]/offset-deg", offset+delta );
1438                 return;
1439                 }
1440         else    { # to left
1441                 var offset = getprop("instrumentation/heading-indicator[1]/offset-deg");
1442                 if( offset == nil ) return;
1443                 setprop("instrumentation/heading-indicator[1]/offset-deg", offset-delta );
1444                 return;
1445                 }
1446         }
1447 else    {       # osn
1448          if( getprop("instrumentation/heading-indicator[0]/serviceable" ) != 1 ) return;
1449         if( arg[0] == 1 ) # to right
1450                 {
1451                 var offset = getprop("instrumentation/heading-indicator[0]/offset-deg");
1452                 if( offset == nil ) return;
1453                 setprop("instrumentation/heading-indicator[0]/offset-deg", offset+delta );
1454                 return;
1455                 }
1456         else    { # to left
1457                 var offset = getprop("instrumentation/heading-indicator[0]/offset-deg");
1458                 if( offset == nil ) return;
1459                 setprop("instrumentation/heading-indicator[0]/offset-deg", offset-delta );
1460                 return;
1461                 }
1462
1463         }
1464 }
1465
1466 # TKS power support
1467
1468 tks_power_1 = func{
1469 if( getprop( "tu154/switches/TKC-power-1" ) == 1.0 )
1470         electrical.AC3x200_bus_1L.add_output( "GA3-1", 10.0);
1471 else electrical.AC3x200_bus_1L.rm_output( "GA3-1" );            
1472 }
1473
1474 tks_bgmk_1 = func{
1475 if( getprop( "tu154/switches/TKC-BGMK-1" ) == 1.0 )
1476         electrical.AC3x200_bus_1L.add_output( "BGMK-1", 10.0);
1477 else electrical.AC3x200_bus_1L.rm_output( "BGMK-1" );           
1478 }
1479
1480 tks_power_2 = func{
1481 if( getprop( "tu154/switches/TKC-power-2" ) == 1.0 )
1482         electrical.AC3x200_bus_3R.add_output( "GA3-2", 10.0);
1483 else electrical.AC3x200_bus_3R.rm_output( "GA3-2" );            
1484 }
1485
1486 tks_bgmk_2 = func{
1487 if( getprop( "tu154/switches/TKC-BGMK-2" ) == 1.0 )
1488         electrical.AC3x200_bus_3R.add_output( "BGMK-2", 10.0);
1489 else electrical.AC3x200_bus_3R.rm_output( "BGMK-2" );           
1490 }
1491
1492
1493 setlistener( "tu154/switches/TKC-power-1", tks_power_1 ,0,0);
1494 setlistener( "tu154/switches/TKC-power-2", tks_power_2 ,0,0);
1495 setlistener( "tu154/switches/TKC-BGMK-1", tks_bgmk_1 ,0,0);
1496 setlistener( "tu154/switches/TKC-BGMK-2", tks_bgmk_2 ,0,0);
1497
1498 # Aug 2009
1499 # Azimuthal error for gyroscope
1500
1501 var last_point = geo.Coord.new();
1502 var current_point = geo.Coord.new();
1503
1504 # Initialise
1505 last_point = geo.aircraft_position();
1506 current_point = last_point;
1507 setprop("/fdm/jsbsim/instrumentation/az-err", 0.0 );
1508
1509 # Azimuth error handler
1510 var tks_az_handler = func{
1511 settimer(tks_az_handler, 60.0 );
1512 current_point = geo.aircraft_position();
1513 if( last_point.distance_to( current_point ) < 1000.0 ) return; # skip small distance
1514
1515 az_err = getprop("/fdm/jsbsim/instrumentation/az-err" );
1516 var zipu = last_point.course_to( current_point );
1517 var ozipu = current_point.course_to( last_point );
1518 az_err += zipu - (ozipu - 180.0);
1519 if( az_err > 180.0 ) az_err -= 360.0;
1520 if( -180.0 > az_err ) az_err += 360.0;
1521 setprop("/fdm/jsbsim/instrumentation/az-err", az_err );
1522 last_point = current_point;
1523 }
1524
1525 settimer(tks_az_handler, 60.0 );
1526
1527
1528 # ************************* End TKS staff ***********************************
1529
1530 #                           KURS-MP frequency support
1531
1532 var kursmp_sync = func{
1533 var frequency = 0.0;
1534 var heading = 0.0;
1535 if( arg[0] == 0 )       # proceed captain panel
1536         { #frequency
1537         var freq_hi = getprop("tu154/instrumentation/kurs-mp-1/digit-f-hi");
1538         if( freq_hi == nil ) return;
1539         var freq_low = getprop("tu154/instrumentation/kurs-mp-1/digit-f-low");
1540         if( freq_low == nil ) return;
1541         frequency = freq_hi + freq_low/100.0;
1542         setprop("instrumentation/nav[0]/frequencies/selected-mhz", frequency );
1543         # heading
1544         var hdg_ones = getprop("tu154/instrumentation/kurs-mp-1/digit-h-ones");
1545         if( hdg_ones == nil ) return;
1546         var hdg_dec = getprop("tu154/instrumentation/kurs-mp-1/digit-h-dec");
1547         if( hdg_dec == nil ) return;
1548         var hdg_hund = getprop("tu154/instrumentation/kurs-mp-1/digit-h-hund");
1549         if( hdg_hund == nil ) return;
1550         heading = hdg_hund * 100 + hdg_dec * 10 + hdg_ones;
1551         if( heading > 359.0 ) { 
1552                 heading = 0.0;
1553                 setprop("tu154/instrumentation/kurs-mp-1/digit-h-hund", 0.0 );
1554                 setprop("tu154/instrumentation/kurs-mp-1/digit-h-dec", 0.0 );
1555                 setprop("tu154/instrumentation/kurs-mp-1/digit-h-ones", 0.0 );
1556                 }
1557         setprop("instrumentation/nav[0]/radials/selected-deg", heading );
1558         return;
1559         }
1560 if( arg[0] == 1 ) # co-pilot
1561         { #frequency
1562         var freq_hi = getprop("tu154/instrumentation/kurs-mp-2/digit-f-hi");
1563         if( freq_hi == nil ) return;
1564         var freq_low = getprop("tu154/instrumentation/kurs-mp-2/digit-f-low");
1565         if( freq_low == nil ) return;
1566         frequency = freq_hi + freq_low/100.0;
1567         setprop("instrumentation/nav[1]/frequencies/selected-mhz", frequency );
1568         # heading
1569         var hdg_ones = getprop("tu154/instrumentation/kurs-mp-2/digit-h-ones");
1570         if( hdg_ones == nil ) return;
1571         var hdg_dec = getprop("tu154/instrumentation/kurs-mp-2/digit-h-dec");
1572         if( hdg_dec == nil ) return;
1573         var hdg_hund = getprop("tu154/instrumentation/kurs-mp-2/digit-h-hund");
1574         if( hdg_hund == nil ) return;
1575         heading = hdg_hund * 100 + hdg_dec * 10 + hdg_ones;
1576                 if( heading > 359.0 ) { 
1577                 heading = 0.0;
1578                 setprop("tu154/instrumentation/kurs-mp-2/digit-h-hund", 0.0 );
1579                 setprop("tu154/instrumentation/kurs-mp-2/digit-h-dec", 0.0 );
1580                 setprop("tu154/instrumentation/kurs-mp-2/digit-h-ones", 0.0 );
1581                 }
1582         setprop("instrumentation/nav[1]/radials/selected-deg", heading );
1583         }
1584 }
1585
1586 # initialize KURS-MP frequencies & headings
1587 var kursmp_init = func{
1588 var freq = getprop("instrumentation/nav[0]/frequencies/selected-mhz");
1589 if( freq == nil ) { settimer( kursmp_init, 1.0 ); return; } # try until success
1590 setprop("tu154/instrumentation/kurs-mp-1/digit-f-hi", int(freq) );
1591 setprop("tu154/instrumentation/kurs-mp-1/digit-f-low", (freq - int(freq) ) * 100 );
1592 var hdg = getprop("instrumentation/nav[0]/radials/selected-deg");
1593 if( hdg == nil ) { settimer( kursmp_init, 1.0 ); return; }
1594 setprop("tu154/instrumentation/kurs-mp-1/digit-h-hund", int(hdg/100) );
1595 setprop("tu154/instrumentation/kurs-mp-1/digit-h-dec", int( (hdg/10.0)-int(hdg/100.0 )*10.0) );
1596 setprop("tu154/instrumentation/kurs-mp-1/digit-h-ones", int(hdg-int(hdg/10.0 )*10.0) );
1597 # second KURS-MP
1598 freq = getprop("instrumentation/nav[1]/frequencies/selected-mhz");
1599 if( freq == nil ) { settimer( kursmp_init, 1.0 ); return; } # try until success
1600 setprop("tu154/instrumentation/kurs-mp-2/digit-f-hi", int(freq) );
1601 setprop("tu154/instrumentation/kurs-mp-2/digit-f-low", (freq - int(freq) ) * 100 );
1602 hdg = getprop("instrumentation/nav[1]/radials/selected-deg");
1603 if( hdg == nil ) { settimer( kursmp_init, 1.0 ); return; }
1604 setprop("tu154/instrumentation/kurs-mp-2/digit-h-hund", int( hdg/100) );
1605 setprop("tu154/instrumentation/kurs-mp-2/digit-h-dec",int( ( hdg / 10.0 )-int( hdg / 100.0 ) * 10.0 ) );
1606 setprop("tu154/instrumentation/kurs-mp-2/digit-h-ones", int( hdg-int( hdg/10.0 )* 10.0 ) );
1607
1608 }
1609
1610 var kursmp_watchdog_1 = func{
1611 #settimer( kursmp_watchdog_1, 0.5 );
1612 if( getprop("instrumentation/nav[0]/in-range" ) == 1 ) return;
1613  if( getprop("tu154/instrumentation/pn-5/gliss" ) == 1.0 ) absu.absu_reset();
1614  if( getprop("tu154/instrumentation/pn-5/az-1" ) == 1.0 ) absu.absu_reset();
1615  if( getprop("tu154/instrumentation/pn-5/zahod" ) == 1.0 ) absu.absu_reset();
1616 }
1617
1618 var kursmp_watchdog_2 = func{
1619 #settimer( kursmp_watchdog_2, 0.5 );
1620 if( getprop("instrumentation/nav[1]/in-range" ) == 1 ) return;
1621 if( getprop("tu154/instrumentation/pn-5/az-2" ) == 1.0 ) absu.absu_reset();
1622 }
1623
1624 setlistener( "instrumentation/nav[0]/in-range", kursmp_watchdog_1, 0,0 );
1625 setlistener( "instrumentation/nav[1]/in-range", kursmp_watchdog_2, 0,0 );
1626
1627 var kursmp_power_1 = func{
1628 if( getprop( "tu154/switches/KURS-MP-1" ) == 1.0 )
1629         electrical.AC3x200_bus_1L.add_output( "KURS-MP-1", 20.0);
1630 else electrical.AC3x200_bus_1L.rm_output( "KURS-MP-1" );                
1631 }
1632
1633 var kursmp_power_2 = func{
1634 if( getprop( "tu154/switches/KURS-MP-2" ) == 1.0 )
1635         electrical.AC3x200_bus_3R.add_output( "KURS-MP-2", 20.0);
1636 else electrical.AC3x200_bus_3R.rm_output( "KURS-MP-2" );                
1637 }
1638
1639 setlistener( "tu154/switches/KURS-MP-1", kursmp_power_1 ,0,0);
1640 setlistener( "tu154/switches/KURS-MP-2", kursmp_power_2 ,0,0);
1641 #kursmp_watchdog_1();
1642 #kursmp_watchdog_2();
1643 kursmp_init();
1644
1645 # ******************************** end KURS-MP *******************************
1646
1647
1648 #RSBN support
1649 var rsbn_set_f_1 = func{
1650 var handle = getprop("tu154/instrumentation/rsbn/handle-1");
1651 if( handle == nil ) handle = 0.0;
1652 var step = arg[0];
1653 if( getprop("tu154/instrumentation/rsbn/mode") == 0)
1654  {
1655   handle = handle + step;
1656   if( handle > 4.0 ) handle = 4.0;
1657   if( handle < 0.0 ) handle = 0.0;
1658   setprop("tu154/instrumentation/rsbn/handle-1", handle );
1659   rsbn_chan_to_f();
1660   return;
1661  }
1662 else {
1663   handle = handle + step/2.5;
1664   if( handle > 4.0 ) handle = 4.0;
1665   if( handle < 0.0 ) handle = 0.0;
1666   setprop("tu154/instrumentation/rsbn/handle-1", handle );
1667   var freq = getprop("tu154/instrumentation/rsbn/frequency" );
1668   if( freq == nil ) freq = 108.0;
1669   var khz = freq - int( freq );
1670   setprop("tu154/instrumentation/rsbn/frequency", 108.0 + handle*2.5 + khz );
1671   setprop("instrumentation/nav[2]/frequencies/selected-mhz", 108.0 + handle*2.5 + khz );
1672   help.rsbn();
1673  } 
1674 }
1675
1676 var rsbn_set_f_2 = func{
1677 var handle = getprop("tu154/instrumentation/rsbn/handle-2");
1678 if( handle == nil ) handle = 0.0;
1679 var step = arg[0];
1680 if( getprop("tu154/instrumentation/rsbn/mode") == 0)
1681   {
1682   handle = handle + step;
1683   if( handle > 9.0 ) handle = 9.0;
1684   if( handle < 0.0 ) handle = 0.0;
1685   setprop("tu154/instrumentation/rsbn/handle-2", handle );
1686   rsbn_chan_to_f();
1687   return;
1688   }
1689 else {
1690   handle = handle + step/20.0;
1691   if( handle > 9.0 ) handle = 9.0;
1692   if( handle < 0.0 ) handle = 0.0;
1693   var freq = getprop("tu154/instrumentation/rsbn/frequency" );
1694   if( freq == nil ) freq = 108.0;
1695   setprop("tu154/instrumentation/rsbn/handle-2", handle );
1696   setprop("tu154/instrumentation/rsbn/frequency", int(freq) + handle/10.0 );
1697   setprop("instrumentation/nav[2]/frequencies/selected-mhz", int(freq) + handle/10.0 );
1698   help.rsbn();
1699   } 
1700 }
1701
1702 var rsbn_set_mode = func{
1703 if( arg[0] == 0 )
1704         {
1705         setprop("tu154/instrumentation/rsbn/mode", 0 );
1706         var handle = getprop("tu154/instrumentation/rsbn/handle-1");
1707         if( handle  == nil ) handle = 0.0;
1708         handle = int( handle ); 
1709         setprop("tu154/instrumentation/rsbn/handle-1", handle );
1710         handle = getprop("tu154/instrumentation/rsbn/handle-2");
1711         if( handle  == nil ) handle = 0.0;
1712         handle = int( handle ); 
1713         setprop("tu154/instrumentation/rsbn/handle-2", handle );
1714         }
1715 else {
1716         setprop("tu154/instrumentation/rsbn/mode", 1 );
1717         }
1718         
1719 rsbn_set_f_1(0);
1720 rsbn_set_f_2(0);
1721
1722 }
1723
1724 var rsbn_chan_to_f = func{
1725 var handle_1 = getprop("tu154/instrumentation/rsbn/handle-1");
1726 var handle_2 = getprop("tu154/instrumentation/rsbn/handle-2");
1727 if( handle_1 == nil ) handle_1 = 0.0;
1728 if( handle_2 == nil ) handle_2 = 0.0;
1729
1730 var channel = handle_1 * 10 + handle_2;
1731 if( channel < 1.0 ) channel = 1.0;
1732 if( channel > 40.0 ) channel = 40.0;
1733
1734 var freq = 959.95 + channel * 0.05;
1735 setprop("tu154/instrumentation/rsbn/frequency", freq );
1736 setprop("instrumentation/nav[2]/frequencies/selected-mhz", freq );
1737 }
1738
1739
1740 var rsbn_power = func{
1741 if( arg[0] == 1 )
1742         {
1743       if( getprop("instrumentation/nav[2]/powered") == 1 )
1744           {
1745           rsbn_set_f_1(0);
1746           rsbn_set_f_2(0);
1747           electrical.AC3x200_bus_1L.add_output( "RSBN", 50.0);
1748           setprop("instrumentation/nav[2]/power-btn", 1 );
1749           setprop("instrumentation/dme[2]/serviceable", 1 );
1750         setprop("tu154/instrumentation/rsbn/serviceable", 1 );
1751           }
1752         }
1753 else { 
1754         electrical.AC3x200_bus_1L.rm_output( "RSBN" );
1755 #       setprop("instrumentation/nav[2]/serviceable", 0 ); 
1756         setprop("instrumentation/dme[2]/serviceable", 0 );
1757         setprop("instrumentation/nav[2]/power-btn", 0 );
1758         setprop("tu154/instrumentation/rsbn/serviceable", 0 );
1759         setprop("instrumentation/nav[2]/powered", 0 );
1760         }
1761 }
1762
1763 var rsbn_pwr_watchdog = func{
1764 if( getprop("instrumentation/nav[2]/powered" ) != 1 ) # power off
1765         {
1766 #       setprop("instrumentation/nav[2]/serviceable", 0 );
1767         setprop("instrumentation/dme[2]/serviceable", 0 );
1768         setprop("instrumentation/nav[2]/power-btn", 0 );
1769 #       setprop("tu154/systems/electrical/indicators/range-avton", 0 );  
1770 #       setprop("tu154/systems/electrical/indicators/azimuth-avton", 0 );
1771         setprop("tu154/instrumentation/rsbn/serviceable", 0 );
1772         return;
1773         }
1774 else    { 
1775         if( getprop( "tu154/switches/RSBN-power" ) == 1.0 ) 
1776             {
1777             setprop("instrumentation/nav[2]/power-btn", 1 );
1778             setprop("instrumentation/dme[2]/serviceable", 1 );
1779             setprop("tu154/instrumentation/rsbn/serviceable", 1 ); 
1780             }
1781         }
1782
1783 if( getprop( "tu154/switches/RSBN-power" ) != 1.0 ) 
1784         {
1785         setprop("tu154/instrumentation/rsbn/serviceable", 0 );
1786         setprop("instrumentation/nav[2]/power-btn", 0 );
1787         setprop("instrumentation/dme[2]/serviceable", 0 );
1788         return;
1789         }
1790 }
1791
1792 setlistener("instrumentation/nav[2]/powered", rsbn_pwr_watchdog, 0,0 );
1793
1794
1795
1796 # ARK support
1797
1798 ark_1_2_handler = func {
1799         var ones = getprop("tu154/instrumentation/ark-15[0]/digit-2-1");
1800         if( ones == nil ) ones = 0.0;
1801         var dec = getprop("tu154/instrumentation/ark-15[0]/digit-2-2");
1802         if( dec == nil ) dec = 0.0;
1803         var hund = getprop("tu154/instrumentation/ark-15[0]/digit-2-3");
1804         if( hund == nil ) hund = 0.0;
1805         var freq = hund * 100 + dec * 10 + ones;
1806         if( getprop("tu154/switches/adf-1-selector") == 1 )
1807                 setprop("instrumentation/adf[0]/frequencies/selected-khz", freq );
1808 }
1809
1810 ark_1_1_handler = func {
1811         var ones = getprop("tu154/instrumentation/ark-15[0]/digit-1-1");
1812         if( ones == nil ) ones = 0.0;
1813         var dec = getprop("tu154/instrumentation/ark-15[0]/digit-1-2");
1814         if( dec == nil ) dec = 0.0;
1815         var hund = getprop("tu154/instrumentation/ark-15[0]/digit-1-3");
1816         if( hund == nil ) hund = 0.0;
1817         var freq = hund * 100 + dec * 10 + ones;
1818         if( getprop("tu154/switches/adf-1-selector") == 0 )
1819                 setprop("instrumentation/adf[0]/frequencies/selected-khz", freq );
1820 }
1821
1822 ark_2_2_handler = func {
1823         var ones = getprop("tu154/instrumentation/ark-15[1]/digit-2-1");
1824         if( ones == nil ) ones = 0.0;
1825         var dec = getprop("tu154/instrumentation/ark-15[1]/digit-2-2");
1826         if( dec == nil ) dec = 0.0;
1827         var hund = getprop("tu154/instrumentation/ark-15[1]/digit-2-3");
1828         if( hund == nil ) hund = 0.0;
1829         var freq = hund * 100 + dec * 10 + ones;
1830         if( getprop("tu154/switches/adf-2-selector") == 1 )
1831                 setprop("instrumentation/adf[1]/frequencies/selected-khz", freq );
1832 }
1833
1834 ark_2_1_handler = func {
1835         var ones = getprop("tu154/instrumentation/ark-15[1]/digit-1-1");
1836         if( ones == nil ) ones = 0.0;
1837         var dec = getprop("tu154/instrumentation/ark-15[1]/digit-1-2");
1838         if( dec == nil ) dec = 0.0;
1839         var hund = getprop("tu154/instrumentation/ark-15[1]/digit-1-3");
1840         if( hund == nil ) hund = 0.0;
1841         var freq = hund * 100 + dec * 10 + ones;
1842         if( getprop("tu154/switches/adf-2-selector") == 0 )
1843                 setprop("instrumentation/adf[1]/frequencies/selected-khz", freq );
1844 }
1845
1846
1847 ark_1_power = func{
1848     if( getprop("tu154/instrumentation/ark-15[0]/powered") == 1 )
1849         {
1850         if( getprop("tu154/switches/adf-power-1")==1 )
1851                 {
1852              electrical.AC3x200_bus_1L.add_output( "ARK-15-1", 20.0);
1853              setprop("instrumentation/adf[0]/serviceable", 1 );
1854                 }
1855         else {
1856              electrical.AC3x200_bus_1L.rm_output( "ARK-15-1" );
1857              setprop("instrumentation/adf[0]/serviceable", 0 );
1858              }
1859         } 
1860    else {
1861         electrical.AC3x200_bus_1L.rm_output( "ARK-15-1" );
1862         setprop("instrumentation/adf[0]/serviceable", 0 );
1863         }
1864 }
1865
1866 ark_2_power = func{
1867     if( getprop("tu154/instrumentation/ark-15[1]/powered") == 1 )
1868         {
1869         if( getprop("tu154/switches/adf-power-2")==1 )
1870                 {
1871              electrical.AC3x200_bus_3R.add_output( "ARK-15-2", 20.0);
1872              setprop("instrumentation/adf[1]/serviceable", 1 );
1873                 }
1874         else {
1875              electrical.AC3x200_bus_3R.rm_output( "ARK-15-2" );
1876              setprop("instrumentation/adf[1]/serviceable", 0 );
1877                 }
1878         } 
1879    else {
1880         electrical.AC3x200_bus_3R.rm_output( "ARK-15-2" );
1881         setprop("instrumentation/adf[1]/serviceable", 0 );
1882         }
1883 }
1884
1885
1886
1887 # read selected and standby ADF frequencies and copy it to ARK
1888 ark_init = func{
1889 var freq = getprop("instrumentation/adf[0]/frequencies/selected-khz");
1890 if( freq == nil ) freq = 0.0;
1891 setprop("tu154/instrumentation/ark-15[0]/digit-1-3", 
1892 int( (freq/100.0) - int( freq/1000.0 )*10.0 ) );
1893 setprop("tu154/instrumentation/ark-15[0]/digit-1-2", 
1894 int( (freq/10.0) - int( freq/100.0 )*10.0 ) );
1895 setprop("tu154/instrumentation/ark-15[0]/digit-1-1", 
1896 int( freq - int( freq/10.0 )*10.0 ) );
1897
1898 freq = getprop("instrumentation/adf[0]/frequencies/standby-khz");
1899 if( freq == nil ) freq = 0.0;
1900 setprop("tu154/instrumentation/ark-15[0]/digit-2-3", 
1901 int( (freq/100.0) - int( freq/1000.0 )*10.0 ) );
1902 setprop("tu154/instrumentation/ark-15[0]/digit-2-2", 
1903 int( (freq/10.0) - int( freq/100.0 )*10.0 ) );
1904 setprop("tu154/instrumentation/ark-15[0]/digit-2-1", 
1905 int( freq - int( freq/10.0 )*10.0 ) );
1906
1907 freq = getprop("instrumentation/adf[1]/frequencies/selected-khz");
1908 if( freq == nil ) freq = 0.0;
1909 setprop("tu154/instrumentation/ark-15[1]/digit-1-3", 
1910 int( (freq/100.0) - int( freq/1000.0 )*10.0 ) );
1911 setprop("tu154/instrumentation/ark-15[1]/digit-1-2", 
1912 int( (freq/10.0) - int( freq/100.0 )*10.0 ) );
1913 setprop("tu154/instrumentation/ark-15[1]/digit-1-1", 
1914 int( freq - int( freq/10.0 )*10.0 ) );
1915
1916 freq = getprop("instrumentation/adf[1]/frequencies/standby-khz");
1917 if( freq == nil ) freq = 0.0;
1918 setprop("tu154/instrumentation/ark-15[1]/digit-2-3", 
1919 int( (freq/100.0) - int( freq/1000.0 )*10.0 ) );
1920 setprop("tu154/instrumentation/ark-15[1]/digit-2-2", 
1921 int( (freq/10.0) - int( freq/100.0 )*10.0 ) );
1922 setprop("tu154/instrumentation/ark-15[1]/digit-2-1", 
1923 int( freq - int( freq/10.0 )*10.0 ) );
1924
1925 }
1926
1927 ark_init();
1928
1929 setlistener("tu154/switches/adf-power-1", ark_1_power ,0,0);
1930 setlistener("tu154/switches/adf-power-2", ark_2_power ,0,0);
1931
1932 setlistener( "tu154/instrumentation/ark-15[0]/powered", ark_1_power ,0,0);
1933 setlistener( "tu154/instrumentation/ark-15[1]/powered", ark_2_power ,0,0);
1934
1935
1936 setlistener( "tu154/switches/adf-1-selector", ark_1_1_handler ,0,0);
1937 setlistener( "tu154/switches/adf-1-selector", ark_1_2_handler ,0,0);
1938
1939 setlistener( "tu154/switches/adf-2-selector", ark_2_1_handler ,0,0);
1940 setlistener( "tu154/switches/adf-2-selector", ark_2_2_handler ,0,0);
1941
1942 setlistener( "tu154/instrumentation/ark-15[0]/digit-1-1", ark_1_1_handler ,0,0);
1943 setlistener( "tu154/instrumentation/ark-15[0]/digit-1-2", ark_1_1_handler ,0,0);
1944 setlistener( "tu154/instrumentation/ark-15[0]/digit-1-3", ark_1_1_handler ,0,0);
1945
1946 setlistener( "tu154/instrumentation/ark-15[0]/digit-2-1", ark_1_2_handler ,0,0);
1947 setlistener( "tu154/instrumentation/ark-15[0]/digit-2-2", ark_1_2_handler ,0,0);
1948 setlistener( "tu154/instrumentation/ark-15[0]/digit-2-3", ark_1_2_handler ,0,0);
1949
1950 setlistener( "tu154/instrumentation/ark-15[1]/digit-1-1", ark_2_1_handler ,0,0);
1951 setlistener( "tu154/instrumentation/ark-15[1]/digit-1-2", ark_2_1_handler ,0,0);
1952 setlistener( "tu154/instrumentation/ark-15[1]/digit-1-3", ark_2_1_handler ,0,0);
1953
1954 setlistener( "tu154/instrumentation/ark-15[1]/digit-2-1", ark_2_2_handler ,0,0);
1955 setlistener( "tu154/instrumentation/ark-15[1]/digit-2-2", ark_2_2_handler ,0,0);
1956 setlistener( "tu154/instrumentation/ark-15[1]/digit-2-3", ark_2_2_handler ,0,0);
1957
1958
1959 # AUASP (UAP-12) power support
1960 auasp_power = func{
1961         if( getprop("tu154/switches/AUASP")==1 )
1962             {
1963              electrical.AC3x200_bus_1L.add_output( "AUASP", 10.0);
1964              setprop("tu154/instrumentation/uap-12/powered", 1 );
1965             }
1966         else {
1967              electrical.AC3x200_bus_1L.rm_output( "AUASP" );
1968              setprop("tu154/instrumentation/uap-12/powered", 0 );
1969             }
1970 }
1971 setlistener("tu154/switches/AUASP", auasp_power, 0,0 );
1972
1973 uap_handler = func{
1974 settimer(uap_handler, 0.0);
1975 if( getprop("tu154/instrumentation/uap-12/powered") == 0.0 ) return;
1976 var n_norm = getprop("fdm/jsbsim/instrumentation/n-norm");
1977 var n_max = getprop("tu154/instrumentation/uap-12/accelerate-max");
1978 var n_min = getprop("tu154/instrumentation/uap-12/accelerate-min");
1979 if( n_norm == nil ) n_norm = -1.0;
1980 if( n_max == nil ) n_max = -1.0;
1981 if( n_min == nil ) n_min = -1.0;
1982 if( n_norm >= n_max ) setprop("tu154/instrumentation/uap-12/accelerate-max", n_norm);
1983 if( n_norm <= n_min ) setprop("tu154/instrumentation/uap-12/accelerate-min", n_norm);
1984 }
1985
1986 uap_handler();
1987
1988 # EUP power support
1989 eup_power = func{
1990         if( getprop("tu154/switches/EUP")==1 )
1991 {
1992              electrical.AC3x200_bus_1L.add_output( "EUP", 5.0);
1993              setprop("instrumentation/turn-indicator/serviceable", 1 );
1994 }
1995         else {
1996              electrical.AC3x200_bus_1L.rm_output( "EUP" );
1997              setprop("instrumentation/turn-indicator/serviceable", 0 );
1998 }
1999 }
2000 setlistener("tu154/switches/EUP", eup_power, 0,0 );
2001
2002
2003 # electrical system update for PNK
2004
2005 var update_electrical = func{
2006 var dc12 = getprop( "tu154/systems/electrical/buses/DC27-bus-L/volts" );
2007 if( dc12 == nil ) return;
2008 if( dc12 > 12.0 ){
2009   if( getprop( "tu154/switches/comm-power-1" ) == 1.0 )
2010           setprop("instrumentation/comm[0]/serviceable", 1 );  
2011   else setprop("instrumentation/comm[0]/serviceable", 0 );  
2012
2013   if( getprop( "tu154/switches/comm-power-2" ) == 1.0 )
2014           setprop("instrumentation/comm[1]/serviceable", 1 );  
2015   else setprop("instrumentation/comm[1]/serviceable", 0 );  
2016   }
2017 else {
2018   setprop("instrumentation/comm[0]/serviceable", 0 );
2019   setprop("instrumentation/comm[1]/serviceable", 0 );
2020   }
2021
2022 var ac200 = getprop( "tu154/systems/electrical/buses/AC3x200-bus-1L/volts" );
2023 if( ac200 == nil ) return; # system not ready yet
2024 if( ac200 > 150.0 )
2025         { # 200 V 400 Hz Line 1 Power OK
2026         setprop("tu154/instrumentation/ark-15[0]/powered", 1 ); 
2027         setprop("instrumentation/dme[0]/serviceable",
2028                 (getprop("tu154/switches/dme-1-power") == 1));
2029         setprop("instrumentation/nav[2]/powered", 1 ); 
2030         setprop("instrumentation/dme[2]/serviceable", 1 );
2031         setprop("tu154/systems/nvu/powered",
2032                 (getprop("tu154/switches/v-51-power") ? 1 : 0));
2033         # KURS-MP left
2034         if( getprop( "tu154/switches/KURS-MP-1" ) == 1.0 )
2035                 {
2036                 setprop("instrumentation/nav[0]/power-btn", 1 );
2037                 setprop("instrumentation/nav[0]/serviceable", 1 );
2038                 setprop("instrumentation/marker-beacon[0]/power-btn", 1 );
2039                 setprop("instrumentation/marker-beacon[0]/serviceable", 1 );            
2040                 }
2041         else    {
2042                 setprop("instrumentation/nav[0]/power-btn", 0 );
2043                 setprop("instrumentation/nav[0]/serviceable", 0 );
2044                 setprop("instrumentation/marker-beacon[0]/power-btn", 0 );
2045                 setprop("instrumentation/marker-beacon[0]/serviceable", 0 );
2046                 }
2047         # GA3-1
2048         if( getprop( "tu154/switches/TKC-power-1" ) == 1.0 )
2049                 setprop("instrumentation/heading-indicator[0]/serviceable", 1 );
2050         else    setprop("instrumentation/heading-indicator[0]/serviceable", 0 );
2051                 
2052         # BGMK-1
2053         if( getprop( "tu154/switches/TKC-BGMK-1" ) == 1.0 )
2054                 setprop("fdm/jsbsim/instrumentation/bgmk-failure-1", 0 );
2055         else    setprop("fdm/jsbsim/instrumentation/bgmk-failure-1", 1 );
2056         # BKK   
2057         if( getprop( "tu154/switches/BKK-power" ) == 1.0 )
2058                 setprop("tu154/instrumentation/bkk/serviceable", 1 );
2059         else    setprop("tu154/instrumentation/bkk/serviceable", 0 );
2060
2061         # DISS  
2062         if( getprop( "tu154/switches/DISS-power" ) == 1.0 )
2063                 setprop("tu154/instrumentation/diss/powered", 1 );
2064         else    setprop("tu154/instrumentation/diss/powered", 0 );
2065
2066         # SVS   
2067         if( getprop( "tu154/switches/SVS-power" ) == 1.0 )
2068                 setprop("tu154/systems/svs/powered", 1 );
2069         else    setprop("tu154/systems/svs/powered", 0 );
2070
2071         # UVID-15       
2072         if( getprop( "tu154/switches/UVID" ) == 1.0 )
2073                 setprop("tu154/instrumentation/altimeter[1]/powered", 1 );
2074         else    setprop("tu154/instrumentation/altimeter[1]/powered", 0 );
2075
2076         # AGR
2077         if( getprop( "tu154/switches/AGR" ) == 1.0 )
2078                 {
2079                 setprop("instrumentation/attitude-indicator[3]/serviceable", 1 );
2080                 setprop("instrumentation/attitude-indicator[3]/caged-flag", 0 );
2081                 }
2082         else    {
2083                 setprop("instrumentation/attitude-indicator[3]/serviceable", 0 );
2084                 setprop("instrumentation/attitude-indicator[3]/caged-flag", 1 );
2085                 bkk_shutdown(3);
2086                 }
2087         # PKP-1
2088         if( getprop( "tu154/switches/PKP-left" ) == 1.0 )
2089                 setprop("instrumentation/attitude-indicator[0]/serviceable", 1 );
2090         else { bkk_shutdown(0); }
2091         # AUASP
2092         if( getprop("tu154/switches/AUASP")==1 )
2093              setprop("tu154/instrumentation/uap-12/powered", 1 );
2094         else setprop("tu154/instrumentation/uap-12/powered", 0 );
2095         # EUP
2096         if( getprop("tu154/switches/EUP")==1 )
2097              setprop("instrumentation/turn-indicator/serviceable", 1 );
2098         else setprop("instrumentation/turn-indicator/serviceable", 0 );
2099
2100         
2101         
2102         }
2103
2104
2105 # turn off all consumers if bus has gone
2106 else    {
2107         setprop("tu154/instrumentation/ark-15[0]/powered", 0 ); 
2108         setprop("instrumentation/dme[0]/serviceable", 0 );
2109         setprop("instrumentation/nav[2]/powered", 0 ); 
2110         setprop("instrumentation/dme[2]/serviceable", 0 );
2111         setprop("tu154/systems/nvu/powered", 0.0 );
2112         setprop("instrumentation/nav[0]/power-btn", 0 );
2113         setprop("instrumentation/nav[0]/serviceable", 0 );
2114         setprop("instrumentation/heading-indicator[0]/serviceable", 0 );
2115         setprop("fdm/jsbsim/instrumentation/bgmk-failure-1", 1 );
2116         setprop("tu154/instrumentation/bkk/serviceable", 0 );
2117         setprop("tu154/instrumentation/diss/powered", 0 );
2118         setprop("tu154/systems/svs/powered", 0 );
2119         setprop("tu154/instrumentation/altimeter[1]/powered", 0 );
2120         setprop("instrumentation/attitude-indicator[3]/caged-flag", 1 );
2121         setprop("tu154/instrumentation/uap-12/powered", 0 );
2122         setprop("instrumentation/turn-indicator/serviceable", 0 );
2123         setprop("instrumentation/marker-beacon[0]/power-btn", 0 );
2124         setprop("instrumentation/marker-beacon[0]/serviceable", 0 );            
2125         
2126         bkk_shutdown(0);
2127         bkk_shutdown(1);
2128         }
2129         
2130 ac200 = getprop( "tu154/systems/electrical/buses/AC3x200-bus-3L/volts" );
2131 if( ac200 == nil ) return; # system not ready yet
2132 if( ac200 > 150.0 )
2133         { # 200 V 400 Hz Line 3 Power OK
2134         setprop("tu154/instrumentation/ark-15[1]/powered", 1 );
2135         setprop("instrumentation/dme[1]/serviceable",
2136                 (getprop("tu154/switches/dme-2-power") == 1));
2137         # KURS-MP right
2138         if( getprop( "tu154/switches/KURS-MP-2" ) == 1.0 )
2139                 {
2140                 setprop("instrumentation/nav[1]/power-btn", 1 );
2141                 setprop("instrumentation/nav[1]/serviceable", 1 );
2142                 }
2143         else    {
2144                 setprop("instrumentation/nav[1]/power-btn", 0 );
2145                 setprop("instrumentation/nav[1]/serviceable", 0 );
2146                 }
2147         # GA3-2
2148         if( getprop( "tu154/switches/TKC-power-2" ) == 1.0 )
2149                 setprop("instrumentation/heading-indicator[1]/serviceable", 1 );
2150         else    setprop("instrumentation/heading-indicator[1]/serviceable", 0 );
2151                 
2152         # BGMK-2
2153         if( getprop( "tu154/switches/TKC-BGMK-2" ) == 1.0 )
2154                 setprop("fdm/jsbsim/instrumentation/bgmk-failure-2", 0 );
2155         else    setprop("fdm/jsbsim/instrumentation/bgmk-failure-2", 1 );
2156
2157         # ABSU
2158         if( getprop( "tu154/switches/SAU-STU" ) == 1.0 )
2159                 {
2160
2161              setprop("tu154/instrumentation/pn-6/serviceable", 1 );
2162                 }
2163         else    {
2164              setprop("tu154/systems/absu/serviceable", 0 );
2165              setprop("tu154/instrumentation/pn-6/serviceable", 0 );
2166                 }
2167 # PKP-2
2168         if( getprop( "tu154/switches/PKP-right" ) == 1.0 )
2169                 setprop("instrumentation/attitude-indicator[1]/serviceable", 1 );
2170         else { bkk_shutdown(1); }
2171 # Contr
2172         if( getprop( "tu154/switches/MGV-contr" ) == 1.0 )
2173                 setprop("instrumentation/attitude-indicator[2]/serviceable", 1 );
2174         else { bkk_shutdown(2); }
2175         
2176         
2177         }
2178
2179 else    {
2180         setprop("tu154/instrumentation/ark-15[1]/powered", 0 ); 
2181         setprop("instrumentation/dme[1]/serviceable", 0 );
2182         setprop("instrumentation/nav[1]/power-btn", 0 );
2183         setprop("instrumentation/nav[1]/serviceable", 0 );
2184         setprop("instrumentation/heading-indicator[1]/serviceable", 0 );
2185         setprop("fdm/jsbsim/instrumentation/bgmk-failure-2", 1 );
2186         setprop("tu154/systems/absu/serviceable", 0 );
2187         setprop("tu154/instrumentation/pn-6/serviceable", 0 );
2188         
2189         bkk_shutdown(2);
2190         bkk_shutdown(3);
2191         }
2192         
2193
2194 }
2195
2196 update_electrical();
2197
2198 # It's shoul be at different place...
2199 # Gear animation support
2200 # for animation only
2201 gear_handler = func{
2202 settimer(gear_handler, 0.0);
2203 var rot = getprop("orientation/pitch-deg");
2204 if( rot == nil ) return;
2205 var offset = getprop("tu154/gear/offset");
2206 if( offset == nil ) offset = 0.0;
2207 var gain = getprop("tu154/gear/gain");
2208 if( gain == nil ) gain = 1.0;
2209 #Left gear
2210 var pressure = getprop("gear/gear[1]/compression-norm");
2211 if( pressure == nil ) return;
2212 if( pressure < 0.1 )setprop("tu154/gear/rotation-left-deg", 8.5 );
2213 else setprop("tu154/gear/rotation-left-deg", rot );
2214 setprop("tu154/gear/compression-left-m", pressure*gain+offset );
2215 # Right gear
2216 pressure = getprop("gear/gear[2]/compression-norm");
2217 if( pressure == nil ) return;
2218 if( pressure < 0.1 ) setprop("tu154/gear/rotation-right-deg", 8.5 );
2219 else setprop("tu154/gear/rotation-right-deg", rot );
2220 setprop("tu154/gear/compression-right-m", pressure*gain+offset );
2221
2222 }
2223
2224 gear_handler();
2225
2226 # Set random gyro deviation
2227 setprop("instrumentation/heading-indicator[0]/offset-deg", 359.0 * rand() );
2228 setprop("instrumentation/heading-indicator[1]/offset-deg", 359.0 * rand() );
2229
2230 setprop("instrumentation/attitude-indicator[0]/internal-pitch-deg",
2231         -70 + 140 * rand());
2232 setprop("instrumentation/attitude-indicator[0]/internal-roll-deg",
2233         -70 + 140 * rand());
2234 setprop("instrumentation/attitude-indicator[1]/internal-pitch-deg",
2235         -70 + 140 * rand());
2236 setprop("instrumentation/attitude-indicator[1]/internal-roll-deg",
2237         -70 + 140 * rand());
2238 setprop("instrumentation/attitude-indicator[2]/internal-pitch-deg",
2239         -70 + 140 * rand());
2240 setprop("instrumentation/attitude-indicator[2]/internal-roll-deg",
2241         -70 + 140 * rand());
2242
2243 #save sound volume and deny sound for startup
2244
2245 var vol = getprop("/sim/sound/volume");
2246           setprop("tu154/volume", vol);  
2247           setprop("/sim/sound/volume", 0.0);
2248 print("PNK started");