From 363dc4cea51be00f39981cc288e95d8b4fe31a1b Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 14 Nov 2018 17:42:06 +0000 Subject: [PATCH] GoFlight MCP and EFIS input configs --- Input/Event/GoFlight/EFIS.xml | 316 +++++++--------- Input/Event/GoFlight/MCP-pro.xml | 622 +++++++++++++++++-------------- Nasal/goflight.nas | 314 ++++++++++++++++ 3 files changed, 792 insertions(+), 460 deletions(-) create mode 100644 Nasal/goflight.nas diff --git a/Input/Event/GoFlight/EFIS.xml b/Input/Event/GoFlight/EFIS.xml index 46c6ddef2..da075e72d 100644 --- a/Input/Event/GoFlight/EFIS.xml +++ b/Input/Event/GoFlight/EFIS.xml @@ -1,23 +1,70 @@ GoFlight GF EFIS - true + false + + + input + 1 + 16 + + 8 + 2 + true + + + 24 + + + + - rel-dial-4 + rel-dial-0 property-adjust /input/goflight/efis/height 0.0 + true 00 11 22 @@ -26,146 +73,17 @@ - - rel-dial-5 - - property-adjust - /input/goflight/efis/baro - 108.0 - 117.95 - true - - - 00 - 11 - 22 - 34 - 48 - - - - - - - - STA Button - button-1 + rel-dial-1 - property-toggle - /instrumentation/efis/inputs/sta - - - - - WXR Button - button-2 - - property-toggle - /instrumentation/efis/inputs/wxr + property-adjust + /instrumentation/efis[0]/inputs/baro-knob TERR Button - button-3 - - nasal - - - - - - ARPT Button - button-4 - - property-toggle - /instrumentation/efis/inputs/arpt - - - - - ARPT Button - button-5 - - nasal - - - - - - ARPT Button - button-6 - - nasal - - - - - - ARPT Button - button-7 - - nasal - - - - - - ARPT Button - button-8 - - nasal - - - - - - TERR Button - button-9 + button-0 property-toggle /instrumentation/efis/inputs/terr @@ -174,7 +92,7 @@ POS Button - button-10 + button-1 property-toggle /instrumentation/efis/inputs/pos @@ -183,7 +101,7 @@ DATA Button - button-11 + button-2 property-toggle /instrumentation/efis/inputs/data @@ -192,7 +110,7 @@ ARPT Button - button-12 + button-3 property-toggle /instrumentation/efis/inputs/arpt @@ -201,7 +119,7 @@ WPT Button - button-13 + button-4 property-toggle /instrumentation/efis/inputs/wpt @@ -210,7 +128,7 @@ STA Button - button-14 + button-5 property-toggle /instrumentation/efis/inputs/sta @@ -219,7 +137,7 @@ WXR Button - button-15 + button-6 property-toggle /instrumentation/efis/inputs/wxr @@ -227,44 +145,56 @@ - ARPT Button - button-16 + + button-7 nasal - + - ARPT Button - button-17 + + button-8 nasal - + + + + nasal + + + - ARPT Button - button-18 + + button-9 nasal - + + + + nasal + + + - ARPT Button - button-19 + + button-10 nasal - + in/HPA toggle - button-20 + button-11 property-toggle /instrumentation/efis/inputs/kpa-mode @@ -272,48 +202,71 @@ - ARPT Button - button-21 + DH/MCA knob push + button-12 nasal - + + + + + property-toggle + /instrumentation/efis/inputs/minimums-mode - ARPT Button - button-22 + + button-13 nasal - + + + + nasal + + + - ARPT Button - button-23 + + button-14 nasal - + + + + nasal + + + - ARPT Button - button-24 + + button-15 nasal - + + + + nasal + + + ADF-L switch - button-25 + button-16 property-assign /instrumentation/efis/inputs/lh-vor-adf - 2 + -1 @@ -327,7 +280,7 @@ VOR-L switch - button-26 + button-17 property-assign /instrumentation/efis/inputs/lh-vor-adf @@ -344,11 +297,11 @@ ADF-R switch - button-27 + button-18 property-assign /instrumentation/efis/inputs/rh-vor-adf - 2 + -1 @@ -361,7 +314,7 @@ VOR-R switch - button-28 + button-19 property-assign /instrumentation/efis/inputs/rh-vor-adf @@ -378,7 +331,7 @@ MTRS Button - button-29 + button-20 nasal @@ -391,8 +344,8 @@ - MTRS Button - button-30 + FPV Button + button-21 nasal @@ -404,17 +357,4 @@ - - DH/MCA knob push - button-21 - - nasal - - - - - property-toggle - /instrumentation/efis/inputs/minimums-mode - - diff --git a/Input/Event/GoFlight/MCP-pro.xml b/Input/Event/GoFlight/MCP-pro.xml index 2fd1ed208..d51c4e3bf 100644 --- a/Input/Event/GoFlight/MCP-pro.xml +++ b/Input/Event/GoFlight/MCP-pro.xml @@ -1,257 +1,303 @@ GoFlight MCP Pro - true + MCP Pro + false 0) { - r ~= padChar; - padCount -=1; - } - - for (var i=0; i < size(s); i += 1) { - if (s[i] == `.`) { - # set the high bit to correspond to the decimal - var lastIndex = size(r) - 1; - r[lastIndex] = r[lastIndex] + 0x80; - } elsif (s[i] == `-`) { - r ~= chr(0x40); - } else { - var digitCode = s[i] - `0`; - r ~= chr(translateDigitToSevenSegment[digitCode]); - } - } - - return r; - } - - var altitudeAlphanumeric = func() { - var alt = getprop("/autopilot/settings/target-altitude-ft"); - var altStr = sprintf("%d", alt); - return encodeString(altStr, 5); - } - - var headingAlphanumeric = func() { - var hdg = getprop("/autopilot/settings/heading-bug-deg"); - return encodeString(sprintf("%d", hdg), 3); - } - - var courseAlphanumeric = func() { - var crs = getprop("/instrumentation/nav[0]/radials/selected-deg"); - return encodeString(sprintf("%d", crs), 3); - } - - var course2Alphanumeric = func() { - var crs = getprop("/instrumentation/nav[1]/radials/selected-deg"); - return encodeString(sprintf("%d", crs), 3); - } - - var speedAlphanumeric = func() { - var spd = getprop("/autopilot/settings/target-speed-kt"); - return encodeString(sprintf("%d", spd), 5); - } - - var vspeedAlphanumeric = func() { - var vs = getprop("/autopilot/settings/vertical-speed-fpm"); - return encodeString(sprintf("%d", vs), 5); - } - - var ledState = func() - { - if (activeChannel == 1) return chr(0x04); - return chr(0x2); - } ]]> - rel-dial - - true - 00 - 11 - 25 - 310 - 420 - + display-brightness + + /input/goflight/mcp/brightness + + + + + + rel-dial-0 property-adjust - /autopilot/settings/target-altitude-ft - 100 + /autopilot/settings/heading-bug-deg + true 0 + 359 + + + true + + 0 + 0 + + + 1 + 1 + + + 2 + 5 + + + 3 + 10 + + + 4 + 30 + + + + + + rel-dial-1 + + property-adjust + /instrumentation/nav[0]/radials/selected-deg + true + 0 + 359 + + + true + + 0 + 0 + + + 1 + 1 + + + 2 + 5 + + + 3 + 10 + + + 4 + 30 + + + + + + rel-dial-2 + + property-adjust + /autopilot/settings/vertical-speed-fpm + -50 + -8000 + 12000 + + + true + + + 0 + 0 + + + 1 + 1 + + + 2 + 2 + + + 3 + 4 + + + 4 + 10 + + + + + + rel-dial-3 + + nasal + + + + true + + + 0 + 0 + + + 1 + 1 + + + 2 + 5 + + + 3 + 10 + + + 4 + 20 + + + + + + + rel-dial-4 + + property-adjust + /instrumentation/nav[1]/radials/selected-deg + true + 0 + 359 + + + true + + + 0 + 0 + + + 1 + 1 + + + 2 + 5 + + + 3 + 10 + + + 4 + 30 + + + + + + rel-dial-5 + + true + + + 0 + 0 + + + 1 + 1 + + + 2 + 10 + + + 3 + 50 + + + 4 + 100 + + + + nasal + - - rel-dial-1 - - property-adjust - /autopilot/settings/heading-bug-deg - true - 0 - 359 - - - true - 00 - 11 - 25 - 310 - 420 - - + + 9 + /input/goflight/mcp/refresh + altitudeAlphanumeric + - - rel-dial-2 - - property-adjust - /instrumentation/nav[0]/radials/selected-deg - true - 0 - 359 - - - true - 00 - 11 - 25 - 310 - 420 - - - - rel-dial-3 - - property-adjust - /autopilot/settings/vertical-speed-fpm - 10 - - - true - 00 - 11 - 25 - 310 - 420 - - + + 7 + /input/goflight/mcp/refresh-headings + headingAlphanumeric + - - rel-dial-4 - - property-adjust - /autopilot/settings/target-speed-kt - 0 - - - true - 00 - 11 - 25 - 310 - 420 - - + + 3 + /input/goflight/mcp/refresh-headings + courseAlphanumeric + - - rel-dial-5 - - property-adjust - /instrumentation/nav[1]/radials/selected-deg - true - 0 - 359 - - - true - 00 - 11 - 25 - 310 - 420 - - + + 11 + /input/goflight/mcp/refresh + vspeedAlphanumeric + + + 5 + /input/goflight/mcp/refresh + speedAlphanumeric + - - 9 - /autopilot/settings/target-altitude-ft - altitudeAlphanumeric - + + 13 + /input/goflight/mcp/refresh-headings + course2Alphanumeric + - - 7 - /autopilot/settings/heading-bug-deg - headingAlphanumeric - - - - 3 - /instrumentation/nav[0]/radials/selected-deg - courseAlphanumeric - - - - 11 - /autopilot/settings/vertical-speed-fpm - vspeedAlphanumeric - - - - 5 - /autopilot/settings/target-speed-kt - speedAlphanumeric - - - - 13 - /instrumentation/nav[1]/radials/selected-deg - course2Alphanumeric - - - + - led-misc + led-misc-0 - 1 - - /gear/gear[0]/indicator-servicable - - /gear/gear[0]/position-norm - 0.9 - - - - - 0 - - - - /gear/gear[0]/indicator-servicable - - /gear/gear[0]/position-norm - 0.9 - - - - + /input/goflight/mcp/led[0] + + led-misc-1 + + /input/goflight/mcp/led[1] + + + + + led-misc-2 + + /input/goflight/mcp/led[2] + + + + + led-misc-3 + + /input/goflight/mcp/led[3] + + button-1 @@ -266,7 +312,7 @@ nasal - + enable @@ -321,8 +367,8 @@ Speed button-9 - nasal - + goflight-mcp-button + @@ -330,8 +376,8 @@ button-10 Level Change - nasal - + goflight-mcp-button + @@ -339,8 +385,8 @@ button-11 Heading - nasal - + goflight-mcp-button + @@ -348,8 +394,8 @@ button-12 Approach - nasal - + goflight-mcp-button + @@ -357,8 +403,8 @@ button-13 Altitude - nasal - + goflight-mcp-button + @@ -366,8 +412,8 @@ button-14 Vertical Speed - nasal - + goflight-mcp-button + @@ -375,9 +421,17 @@ button-15 Disengage Bar - nasal - + property-assign + /input/goflight/mcp/ap-disengage + 1 + + + property-assign + /input/goflight/mcp/ap-disengage + 0 + + @@ -385,17 +439,25 @@ button-16 F/O FD Enable - nasal - + property-assign + /input/goflight/mcp/fo-fd-enabled + 1 + + + property-assign + /input/goflight/mcp/fo-fd-enabled + 0 + + button-17 Altitude Intervention - nasal - + goflight-mcp-button + @@ -403,8 +465,8 @@ button-18 CWS-A - nasal - + goflight-mcp-button + @@ -412,8 +474,8 @@ button-19 CWS-B - nasal - + goflight-mcp-button + @@ -421,8 +483,8 @@ button-20 IAS knob push - nasal - + goflight-mcp-button + @@ -430,8 +492,8 @@ button-21 HDG knob push - nasal - + goflight-mcp-button + @@ -439,8 +501,8 @@ button-22 Altitude Knob Push - nasal - + goflight-mcp-button + @@ -448,17 +510,25 @@ button-23 Captain's FD Enable - nasal - + property-assign + /input/goflight/mcp/captain-fd-enabled + 1 + + + property-assign + /input/goflight/mcp/captain-fd-enabled + 0 + + button-24 N1 select - nasal - + goflight-mcp-button + @@ -466,8 +536,8 @@ button-25 VNAV - nasal - + goflight-mcp-button + @@ -475,8 +545,8 @@ button-26 LNAV - nasal - + goflight-mcp-button + @@ -484,8 +554,8 @@ button-27 CMD A - nasal - + goflight-mcp-button + @@ -493,8 +563,8 @@ button-28 CMD B - nasal - + goflight-mcp-button + @@ -502,17 +572,25 @@ button-29 AT arm - nasal - + property-assign + /input/goflight/mcp/autothrottle-armed + 1 + + + property-assign + /input/goflight/mcp/autothrottle-armed + 0 + + button-30 Soeed crossover - nasal - + goflight-mcp-button + @@ -520,8 +598,8 @@ button-31 Speed intervention - nasal - + goflight-mcp-button + @@ -529,8 +607,8 @@ button-32 VOR / Localizer - nasal - + goflight-mcp-button + diff --git a/Nasal/goflight.nas b/Nasal/goflight.nas new file mode 100644 index 000000000..539e36026 --- /dev/null +++ b/Nasal/goflight.nas @@ -0,0 +1,314 @@ +# helpers for working with GoFlight input devices + +# map decimal digits 0..9 to standard 7-segment LCD pattern +var translateDigitToSevenSegment = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x67]; + +var formatFrequencyMHz = func(freqMhz, fieldWidth) +{ + return bytesForString(sprintf("%.3f", freqMhz), fieldWidth); +} + +var formatFrequencyKHz = func(freqKhz, fieldWidth) +{ + return bytesForString(sprintf("%6.2f", freqKhz), fieldWidth); +} + +var bytesForString = func(s, fieldWidth) +{ + var padCount = fieldWidth - size(s); + var r = ""; + + while (padCount > 0) { + r ~= chr(0); + padCount -=1; + } + + for (var i=0; i < size(s); i += 1) { + if (s[i] == `.`) { + # set the high bit to correspond to the decimal + var lastIndex = size(r) - 1; + r[lastIndex] = r[lastIndex] + 0x80; + } else if (s[i] == ` `) { # spaces + r ~= chr(0); + } else if (s[i] == `-`) { # negative + r ~= chr(0x40); + } else { + var digitCode = s[i] - `0`; + r ~= chr(translateDigitToSevenSegment[digitCode]); + } + } + + return r; +} + +# TEST +# STBY +# OFF +# XPDR +# TA +# TA/RA + + +var translateTo14Segment = { + 32: [0x0, 0x0], # space + 65: [0x22, 0x37], # A + 66: [0x0A, 0x8f], + 67: [0x00, 0x39], + 68: [0x08, 0x8f], # uppercase D + 69: [0x22, 0x39], + 70: [0x20, 0x31], # F + 77: [0x00, 0x00], # upper M + 78: [0x00, 0x00], # upper N + 79: [0x00, 0x3f], # upper O + 80: [0x22, 0x33], # upper P + 82: [0x26, 0x33], # upper R + 83: [0x22, 0x2d], # upper S + 84: [0x08, 0x81], # T + 88: [0x15, 0x40], # X + 89: [0x09, 0x40] # Y +}; + +var formatFourteenSegment = func(s, fieldWidth) +{ + var r = []; + for (var i=0; i < size(s); i += 1) { + var ch = s[i]; + if (!contains(translateTo14Segment, ch)) { + debug.dump('No 14 segment mapping for:', ch); + } else { + var t = translateTo14Segment[s[i]]; + append(r, t[0]); + append(r, t[1]); + } + } + return r; +} + +var reverseBytes = func(bytes) +{ + var r=[]; + for (var i = size(bytes) - 1; i >=0; i -=1) { + append(r, bytes[i]); + } + return r; +} + +var MFRController = { + + new: func(prefix) + { + var m = { + parents: [MFRController] + }; + + # m._hideTimer = maketimer(m.DELAY, m, Tooltip._hideTimeout); + # m._hideTimer.singleShot = 1; + + return m; + } +}; + +var mcp = { + init: func() + { + me._speedKnotsProp = props.globals.getNode("/autopilot/settings/target-speed-kt", 1); + me._speedMachProp = props.globals.getNode("/autopilot/settings/target-speed-mach", 1); + me._altitudeFtProp = props.globals.getNode("/autopilot/settings/target-altitude-ft", 1); + me._vsFPMProp = props.globals.getNode("/autopilot/settings/vertical-speed-fpm", 1); + me._headingProp = props.globals.getNode("/autopilot/settings/heading-bug-deg", 1); + me._course1Prop = props.globals.getNode("/instrumentation/nav[0]/radials/selected-deg", 1); + me._course2Prop = props.globals.getNode("/instrumentation/nav[1]/radials/selected-deg", 1); + + me._useMach = 0; + me._refreshProp = props.globals.getNode("/input/goflight/mcp/refresh", 1); + me._refreshHeadingProp = props.globals.getNode("/input/goflight/mcp/refresh-headings", 1); + + me._blankVSWindow = props.globals.getNode("/input/goflight/mcp/blank-vs-window", 1); + + me._ledProps = []; + for (var l=0; l<4; l+=1) { + var node = props.globals.getNode("/input/goflight/mcp/led[" ~ l ~ "]", 1); + node.setIntValue(0); + append(me._ledProps, node); + } + + setlistener(me._speedKnotsProp, func { me.doRefresh(); } ); + setlistener(me._speedMachProp, func { me.doRefresh(); }); + setlistener(me._altitudeFtProp, func { me.doRefresh(); }); + setlistener(me._vsFPMProp, func { me.doRefresh(); }); + setlistener(me._blankVSWindow, func { me.doRefresh(); }); + + setlistener(me._headingProp, func { me.doRefreshHeading(); }); + setlistener(me._course1Prop, func { me.doRefreshHeading(); }); + setlistener(me._course2Prop, func { me.doRefreshHeading(); }); + + me.doRefresh(); + me.doRefreshHeading(); + + print("GoFlight MCP init done"); + }, + + setAltitudeFtProp: func(path) + { + me._altitudeFtProp = props.globals.getNode(path, 1); + setlistener(me._altitudeFtProp, func { me.doRefresh(); }); + me.doRefresh(); + }, + + doRefresh: func() + { + me._refreshProp.setIntValue(0); + }, + + doRefreshHeading: func() + { + me._refreshHeadingProp.setIntValue(0); + }, + + setMachMode: func(useMach) + { + me._useMach = useMach; + me.doRefresh(); + }, + + altitudeData: func() + { + # if window is blanked, return empty data + var alt = me._altitudeFtProp.getValue(); + return bytesForString(sprintf("%d", alt), 5); + }, + + vsData: func() + { + # if window is blanked, return empty data + if (me._blankVSWindow.getValue()) { + return bytesForString(" ", 5); + } + + var vs = me._vsFPMProp.getValue(); + return bytesForString(sprintf("%d", vs), 5); + }, + + speedData: func() + { + if (me._useMach) { + var mach = me._speedMachProp.getValue(); + return bytesForString(sprintf("%0.3f ", mach), 5); + } + + var spd = me._speedKnotsProp.getValue(); + return bytesForString(sprintf("%d", spd), 5); + }, + + adjustSpeed: func(val) + { + if (me._useMach) { + var mach = me._speedMachProp.getValue(); + me._speedMachProp.setDoubleValue(mach + (val * 0.01)); + return; + } + + var spd = me._speedKnotsProp.getValue(); + me._speedKnotsProp.setIntValue(spd + val); + }, + + adjustAltitude: func(val) + { + var alt = me._altitudeFtProp.getValue(); + me._altitudeFtProp.setIntValue(alt + val); + }, + + headingData: func() + { + var h = me._headingProp.getValue(); + return bytesForString(sprintf("%0d", h), 3); + }, + + course1Data: func() + { + var h = me._course1Prop.getValue(); + return bytesForString(sprintf("%0d", h), 3); + }, + + course2Data: func() + { + var h = me._course2Prop.getValue(); + return bytesForString(sprintf("%0d", h), 3); + }, + + _ledNames: { + 'SPEED': [1, 0], + 'LVL-CHG': [1, 1], + 'HDG-SEL': [1, 2], + 'APP': [1,3], + 'ALT-HLD': [1,4], + 'V/S': [1,5], + 'F/O F/D': [1,7], + # bank 2 + 'CWS A': [2,1], + 'CWS B': [2,2], + 'CAP F/D': [2,6], + 'N1': [2, 7], + # bank 3 + 'VNAV': [3,0], + 'LNAV': [3,1], + 'CMD A': [3,2], + 'CMD B': [3,3], + 'A/T ARM': [3,4], + 'VOR-LOC': [3,7], + }, + + watchPropertyForLED: func(prop, ledName) + { + if (!contains(me._ledNames, ledName)) { + printlog('warn', 'Unknown GoFlight MCP LED:' ~ ledName); + return; + } + + var ledData = me._ledNames[ledName]; + setlistener(prop, func(n) { me.setLED(ledData, n.getValue()); }); + }, + + setLED: func(data, b) + { + # data is a pair of ints; the LED node and the bit within + var node = me._ledProps[data[0]]; + var ledBits = node.getValue(); + node.setIntValue(bits.switch(ledBits, data[1], b)); + } +}; + +var flapPositions = []; +var flapsNode = nil; + +_setlistener("/sim/signals/nasal-dir-initialized", func { + mcp.init(); + + # build flap axis quantisation data + flapsNode = props.globals.getNode("/controls/flight/flaps"); + + foreach (var c; props.globals.getNode("/sim/flaps").getChildren("setting")) { + var step = c.getValue(); + append(flapPositions, step); + } + +}); + +var flapsAxisQuantized = func(val) +{ + var normVal = (val + 1) * 0.5; + var numSteps = size(flapPositions); + for (var i=1; i