fnd_page.nas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # ==============================================================================
  2. # Original Boeing 747-400 pfd by Gijs de Rooy
  3. # Modified for 737-800 by Michael Soitanen
  4. # Modified for EC145 by litzi
  5. # ==============================================================================
  6. var ROSESC = 0.58;
  7. var ROSEX = 180;
  8. var ROSEY = ROSEX * ROSESC;
  9. var DMEFACTOR = 0.0005399;
  10. var ALTFACTOR = (651-464)/400;
  11. var FPS2FPM = 60;
  12. var SHIFT_THRES = 0.5;
  13. var ROT_THRES = 0.1;
  14. # include some helper functions for the FND page if not already loaded
  15. if (!defined("FND_FUNC_LOADED"))
  16. io.include(HELIONIXPATH ~ "Nasal/fnd_func.nas");
  17. # add some specific sensors for the Helionix displays of h145 (bk117-D2),
  18. # if not already defined
  19. if ( contains(adc,"ralt_lut") == 0) {
  20. adc["ralt_lut"] = LUT.new([[0,0], [100,123.8], [1000,678.5], [2200,1173.5], [2500,1500]]);
  21. adc["agllut"] = Sensor.new({"function": func {return adc.ralt_lut.get(adc.agl.val)} });
  22. for (var li=0; li<7; li+=1) {
  23. foreach (var j; [0,1,2]) {
  24. adc["masterlist_"~li~"_"~j] = Sensor.new({
  25. prop: "instrumentation/efis/fnd/masterlist["~li~"]/msg["~j~"]",
  26. type: "STRING"
  27. });
  28. }
  29. adc["masterlist_"~li~"_level"] = Sensor.new({
  30. prop: "instrumentation/efis/fnd/masterlist["~li~"]/level",
  31. type: "FLOAT"
  32. });
  33. }
  34. }
  35. page_setup["fnd"] = func (i) {
  36. p = mfd[i].add_page("fnd", HELIONIXPATH~"svg/fnd.svg");
  37. generateAltLadder(p, pitch=ALTFACTOR*100);
  38. # MFD top row button labels
  39. # ============================
  40. p.add_cond("fndBtn", {offset: 0 } );
  41. p.add_cond("vmdBtn", {offset: isin("vmd", mfd[i].pages) > -1 } );
  42. p.add_cond("navdBtn", {offset: isin("navd", mfd[i].pages) > -1 } );
  43. p.add_cond("dmapBtn", {offset: isin("dmap", mfd[i].pages) > -1 } );
  44. p.add_cond("miscBtn", {offset: isin("misc", mfd[i].pages) > -1 } );
  45. p.add_cond("efbBtn", {offset: isin("efb", mfd[i].pages) > -1 } );
  46. # alt tape elements animation
  47. # ============================
  48. var raltoffset = getprop("/instrumentation/efis/fnd/radar-alt-offset-ft");
  49. p.add_direct("altBug", adc.alt, func(o,c) o.setTranslation(0, -ALTFACTOR*(adc.aptargetAlt.val - adc.alt.val) ) );
  50. p.add_trans("altBack", "y-shift", {sensor: adc.agl, min: -280, max: 280, scale: 130/280} );
  51. p.add_direct("aglBug", adc.agl, func(o,c) o.setTranslation(0, adc.agllut.val - adc.ralt_lut.get(getprop("/autopilot/settings/target-agl-ft") or 0) ));
  52. p.add_trans("radarAlttape", "y-shift", {sensor: adc.agllut, offset: -raltoffset});
  53. # move speed and fli tapes, animate ai elements
  54. # ============================
  55. p.add_direct("iasBug", adc.ias, func(o,c) o.setTranslation(0, (adc.ias.val - adc.aptargetSpeed.val)*3.19));
  56. p.add_trans("flitape", "y-shift", {sensor: adc.fli, scale: 90.3, offset: 0, max: 10, min: 0 });
  57. p.add_trans("speedtape", "y-shift", {sensor: adc.ias, max:350, min:-20, scale: 3.19});
  58. p.add_trans("Alt_Group", "y-shift", {sensor: adc.alt, scale: ALTFACTOR });
  59. #TODO Experimental: testbench for property rule transformations
  60. #p.link2rule("flitape", "instrumentation/efis/fnd/fli-tape", {type:"y-shift", scale:90.3, offset:0, max:10, min:0, abs:0, mod:nil});
  61. #p.link2rule("speedtape", "velocities/airspeed-kt", {type:"y-shift", scale:3.19, offset:0, max:350, min:-20, abs:0, mod:nil});
  62. p.add_trans("fli_sync", "y-shift", {sensor: adc.fliSync, scale: -90.3, offset: 0, max: 10, min: -10 });
  63. p.add_trans("fli_ttop", "y-shift", {sensor: adc.fliTtop, scale: -90.3, offset: 0, max: 10, min: -10 });
  64. p.add_trans("fli_mcp", "y-scale", {sensor: adc.add( { function: func {getprop("instrumentation/efis/fnd/fli-top") - getprop("instrumentation/efis/fnd/fli-mcp") }}) });
  65. p.add_trans("fli_mcp", "y-shift", {sensor: adc.fliMcp, scale: -90.3, offset: 0, max: 10, min: -10 });
  66. p.add_trans("horizon", "y-shift", {sensor: adc.pitch, scale: 3.6, max: 90 , min:-90});
  67. p.add_trans("horizon", "rotation", {sensor: adc.roll, scale: -1});
  68. p.add_trans("horizonNums", "y-shift", {sensor: adc.pitch, scale: 3.6, max: 90 , min:-90});
  69. p.add_trans("horizonNums", "rotation", {sensor: adc.roll, scale: -1});
  70. p.add_trans("rollPointer", "rotation", {sensor: adc.roll, scale: -1 });
  71. p.add_trans("slipSkid", "x-shift", {sensor: adc.slipskid, scale: -25 });
  72. p.add_text("aglNum", {sensor: adc.agl, format: "%d", offset: -raltoffset, trunc: "abs"});
  73. p.add_cond("aglNum", {sensor: adc.agl, lessthan: 1000 });
  74. # move vsi needle and numerical indication
  75. # ============================
  76. p.add_trans("vsi", "rotation", {sensor: adc.vs, scale:-1.2, max:35, min:-35});
  77. p.add_trans_grp(["vsi", "vsiNum"], "y-shift", {sensor: adc.vs, scale: -84/2000*FPS2FPM, max:35, min:-35 });
  78. p.add_trans("vsBug", "y-shift", {sensor: adc.aptargetRoc, scale: -84/2000*FPS2FPM, max:35, min:-35 });
  79. p.add_trans("vsiNum", "y-shift", {sensor: adc.vsiNumVis });
  80. p.add_text("vsiNum", {sensor: adc.vs, trunc: "abs", scale: FPS2FPM/100, format: "%2.0f" });
  81. p.add_cond("vsiNum", {sensor: adc.vs, notin: [-3,3] });
  82. # Rose transformations
  83. # Bearing Needles
  84. # ============================
  85. p.add_trans("bear1Needle", "rotation", {sensor: adc.add({function: func navSrcBear(adc.bearsrc0[i].val), timer: FAST}) });
  86. p.add_cond("bear1Needle", {sensor: adc.add({function: func navSrcInrange(adc.bearsrc0[i].val), timer: SLOW}) });
  87. p.add_trans("bear2Needle", "rotation", {sensor: adc.add({function: func navSrcBear(adc.bearsrc1[i].val), timer: FAST}) });
  88. p.add_cond("bear2Needle", {sensor: adc.add({function: func navSrcInrange(adc.bearsrc1[i].val), timer: SLOW}) });
  89. # course and CDI
  90. # ============================
  91. p.add_trans("Rose_Group", "rotation", {sensor: adc.heading, scale: -1});
  92. p.add_trans("hdgBug", "rotation", {sensor: adc.headbug});
  93. p.add_trans("cdiNeedle", "x-shift", {sensor: adc.add( {function: func navSrcDefl(adc.navsrc[i].val), timer:FAST }), scale: 7.5 });
  94. p.add_cond_grp(["cdiNeedle", "toFrom"], {sensor: adc.add( {function: func navSrcInrange(adc.navsrc[i].val), timer: SLOW }) });
  95. p.add_trans("toFrom", "rotation", {sensor: adc.add( {function: func { (adc.navsrc[i].val == "NAV1") ? adc.nav0from.val : adc.nav1from.val }, timer: SLOW}), scale:180});
  96. p.add_trans("Cdi_Group", "rotation", {sensor: adc.add( {function: func navSrcCrs(adc.navsrc[i].val), timer:FAST}) });
  97. p.add_trans("Rose_Group", "y-scale", {offset: ROSESC});
  98. p.add_trans("gsNeedle", "y-shift", {sensor: adc.add({function: func { (adc.navsrc[i].val == "NAV1") ? adc.nav0gsdef.val : adc.nav1gsdef.val }, timer:FAST}), scale: -65});
  99. p.add_cond_grp(["gsNeedle", "gsScale"], {sensor: adc.add({function: func { (adc.navsrc[i].val == "NAV1") ? adc.nav0gsinrange.val : adc.nav1gsinrange.val}, timer:SLOW}) });
  100. p.add_trans("speedTrend", "y-scale", {sensor: adc.iasTrend, scale: 0.02, max: 40, min:-40});
  101. p.add_cond("Mrk_Group", {sensor: adc.ilsmarker });
  102. p.add_text("MrkLabel", {sensor: adc.add( {function: func { ( adc.ilsin.val ? "I" : (adc.ilsmid.val ? "M" : (adc.ilsout.val ? "O" : "" )))}, timer: SLOW, type: "STRING" }) });
  103. # lots of text
  104. # for nav aids to update
  105. # ============================
  106. # if FMS show "GPS" else show Nav frequency
  107. p.add_text("navFrq", {sensor: adc.navsrc[i], funcof: "navSrcFrq" });
  108. p.add_cond("navFrq", {sensor: adc.navsrc[i], notequal: "FMS" });
  109. p.add_text("navID", {sensor: adc.navsrc[i], funcof:"navSrcId" });
  110. p.add_text("navSrc", {sensor: adc.navsrc[i], funcof: "navSrcType" });
  111. p.add_text("crs", {sensor: adc.add({function: func navSrcCrs(adc.navsrc[i].val), timer:SLOW, type:"STRING"}), format: "%3.0f"});
  112. p.add_text("navDME", {sensor: adc.add( {function: func navSrcDist(adc.navsrc[i].val), timer: SLOW, type: "STRING" }) });
  113. p.add_cond("navDME", {sensor: adc.add( {function: func navSrcInrange(adc.navsrc[i].val), timer: SLOW, type: "BOOL"}) });
  114. p.add_cond("navGPS", {sensor: adc.navsrc[i], equals: "FMS" });
  115. adc["navTTG"~i] = Sensor.new({function: func navSrcTTG(adc.navsrc[i].val), timer: SLOW});
  116. p.add_text("navTTG", {sensor: adc["navTTG"~i], format: "%i mn" });
  117. p.add_cond("navTTG", {sensor: adc["navTTG"~i], between: [1, 120] });
  118. p.add_text("bearingSrc1", {sensor: adc.bearsrc0[i], funcof: "navSrcType" });
  119. p.add_text("bearingSrc2", {sensor: adc.bearsrc1[i], funcof: "navSrcType" });
  120. p.add_text("bearingFrq1", {sensor: adc.bearsrc0[i], funcof: "navSrcFrq" });
  121. p.add_text("bearingFrq2", {sensor: adc.bearsrc1[i], funcof: "navSrcFrq" });
  122. p.add_text("bearingDME1", {sensor: adc.add( {function: func navSrcDist(adc.bearsrc0[i].val), timer: SLOW, type: "STRING" }) });
  123. p.add_cond("bearingDME1", {sensor: adc.add( {function: func navSrcInrange(adc.bearsrc0[i].val), timer: SLOW, type: "STRING" }) });
  124. p.add_text("bearingDME2", {sensor: adc.add( {function: func navSrcDist(adc.bearsrc1[i].val), timer: SLOW, type: "STRING" }) });
  125. p.add_cond("bearingDME2", {sensor: adc.add( {function: func navSrcInrange(adc.bearsrc1[i].val), timer: SLOW, type: "STRING" }) });
  126. # /instrumentation/nav[0]/has-gs --> navSrc VOR1/ILS1
  127. # fuel indicators
  128. # and rotor and eng rmp
  129. # ============================
  130. p.add_trans("fuelTotal", "y-scale", {sensor: adc.tank0 });
  131. p.add_trans("fuelL", "y-scale", {sensor: adc.tank1 });
  132. p.add_trans("fuelR", "y-scale", {sensor: adc.tank2 });
  133. p.add_text("fuelNum", {sensor: adc.tank_total, scale: LB2KG, format: "%3.0f Kg" });
  134. p.add_text("nrNum", {sensor: adc.nr, format: "%d"});
  135. p.add_trans_grp(["nrNeedle1", "nrNeedle2"], "rotation", {sensor: adc.nr, min: 80 , max:120, scale: 180/40, offset: -360});
  136. p.add_trans("n2_1Needle", "rotation", {sensor: adc.n2_1, min: 80 , max:120, scale: 180/40, offset: -360});
  137. p.add_trans("n2_2Needle", "rotation", {sensor: adc.n2_2, min: 80 , max:120, scale: 180/40, offset: -360});
  138. # note: this works also
  139. # p.add_text("fuelNum", {function: func sprintf("%3.0fKg", getprop("consumables/fuel/tank[0]/level-norm")*500) });
  140. p.add_text("OAT", {sensor: adc.oat, format: "%3.0f°C" });
  141. p.add_text("qnh", {sensor: adc.qnhDisplay });
  142. # AP annunciators text items
  143. #
  144. # ============================
  145. p.add_text("altTarget", {sensor: adc.aptargetAlt, format: "%d"});
  146. p.add_cond_grp(["altTarget", "altBug"], {sensor: adc.altTargetVis });
  147. p.add_text("aglTarget", {sensor: adc.aptargetAgl, format: "%3.0f"});
  148. p.add_cond_grp(["aglTarget", "aglBug"], {sensor: adc.aglTargetVis});
  149. p.add_cond("iasBug", {sensor: adc.apspeed, equals: "speed-with-pitch-trim" });
  150. p.add_cond("vsBug", {sensor: adc.vsBugVis });
  151. p.add_text("apLockRoll", {sensor: adc.apLockRoll });
  152. p.add_text("apArmRoll", {sensor: adc.apArmRoll });
  153. p.add_text("apLockPitch", {sensor: adc.apLockPitch });
  154. p.add_text("apArmPitch", {sensor: adc.apArmPitch });
  155. p.add_text("apLockColl", {sensor: adc.apLockColl });
  156. p.add_text("apArmColl", {sensor: adc.apArmColl });
  157. # master list text items
  158. # and color animation
  159. # ============================
  160. var masterlistcolors = [
  161. [2, [0,1,0]],
  162. [nil, [1,0.75,0]],
  163. [4, [1,0,0]]
  164. ];
  165. for (var li=0; li<7; li+=1) {
  166. foreach (var j; [0,1,2]) {
  167. p.add_text("ml_"~li~"_"~j, {sensor: adc["masterlist_" ~ li ~ "_" ~ j]});
  168. p.add_color_range("ml_"~li~"_"~j, adc["masterlist_"~li~"_level"], masterlistcolors);
  169. }
  170. }
  171. # translate rose numerals in elliptic orbit
  172. # around center of compass rose
  173. # ============================
  174. var HdgNums = Rosenumerals.new(p, ROSEX, ROSEY);
  175. Generatewindbarb(p);
  176. }; # func