diff --git a/Aircraft/Generic/century2b.nas b/Aircraft/Generic/century2b.nas new file mode 100644 index 000000000..6c62731a1 --- /dev/null +++ b/Aircraft/Generic/century2b.nas @@ -0,0 +1,531 @@ +## +# Century IIB Autopilot System +# Models behavior of the Century IIB autopilot +# one axis. +# +# One would also need the autopilot configuration file +# CENTURYIIB.xml (in pa24-250/Systems) and the animation and panel +# and .ac files in pa24-250/Models/Century-IIB. +# +# +# Written by Dave Perry to match functionality described in +# +# CENTURY IIB +# AUTOPILOT FLIGHT SYSTEM +# PILOT'S OPERATING HANDBOOK +# MARCH 1981 68S75 +# +# Draws heavily from the kap140 system written by Vegard Ovesen +## + +# Properties + +locks = "/autopilot/CENTURYIIB/locks"; +settings = "/autopilot/CENTURYIIB/settings"; +internal = "/autopilot/internal"; +flightControls = "/controls/flight"; +autopilotControls = "/autopilot/CENTURYIIB/controls"; + +# locks +propLocks = props.globals.getNode(locks, 1); + +lockAprHold = propLocks.getNode("apr-hold", 1); +lockHdgHold = propLocks.getNode("hdg-hold", 1); +lockNavHold = propLocks.getNode("nav-hold", 1); +lockOmniHold = propLocks.getNode("omni-hold", 1); +lockRevHold = propLocks.getNode("rev-hold", 1); +lockRollAxis = propLocks.getNode("roll-axis", 1); +lockRollMode = propLocks.getNode("roll-mode", 1); +lockRollArm = propLocks.getNode("roll-arm", 1); + + +rollModes = { "OFF" : 0, "ROL" : 1, "HDG" : 2, "OMNI" : 3, "NAV" : 4, "REV" : 5, "APR" : 6 }; +rollArmModes = { "OFF" : 0, "NAV" : 1, "OMNI" : 2, "APR" : 3, "REV" : 4 }; + +# settings +propSettings = props.globals.getNode(settings, 1); + +settingTargetInterceptAngle = propSettings.getNode("target-intercept-angle", 1); +settingTargetInterceptAngle = propSettings.getNode("target-intercept-angle", 1); +settingTargetRollDeg = propSettings.getNode("target-roll-deg", 1); +settingRollKnobDeg = propSettings.getNode("roll-knob-deg", 1); + +#Flight controls +propFlightControls = props.globals.getNode(flightControls, 1); + +elevatorControl = propFlightControls.getNode("elevator", 1); +elevatorTrimControl = propFlightControls.getNode("elevator-trim", 1); + +#Autopilot controls +propAutopilotControls = props.globals.getNode(autopilotControls, 1); + +rollControl = propAutopilotControls.getNode("roll", 1); +# values 0 (A/P switch off) and 1 (A/P switch on) +hdgControl = propAutopilotControls.getNode("hdg", 1); +# values 0 (hdg switch off) and 1 (hdg switch on) +modeControl = propAutopilotControls.getNode("mode", 1); +# values 0 NAV, 1 OMNI, 2 HDG, 3 LOC, 4 LOC REV + +headingNeedleDeflection = "/instrumentation/nav/heading-needle-deflection"; +power="/systems/electrical/outputs/autopilot"; +filteredHeadingNeedleDeflection = "/autopilot/internal/filtered-heading-needle-deflection"; + +# Initialize Variables +valueTest = 0; +lastValue = 0; +newValue = 0; +minVoltageLimit = 8.0; +oldMode = 2; +rollControl.setDoubleValue(0.0); +hdgControl.setDoubleValue(0.0); +modeControl.setDoubleValue(2.0); + +apInit = func { + ##print("ap init"); + + ## + # Initialises the autopilot. + ## + + lockAprHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(0); + lockRollMode.setIntValue(rollModes["OFF"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); +# Reset the memory for power down or power up + settingTargetInterceptAngle.setDoubleValue(0.0); + settingTargetRollDeg.setDoubleValue(0.0); + settingRollKnobDeg.setDoubleValue(0.0); +} + +apPower = func { + +## Monitor autopilot power +## Call apInit if the power is too low + + if (getprop(power) < minVoltageLimit) { + newValue = 0; + } else { + newValue = 1; + } + + valueTest = newValue - lastValue; +# print("v_test = ", v_test); + if (valueTest > 0.5) { + # autopilot just powered up + print("power up"); + apInit(); + } elsif (valueTest < -0.5) { + # autopilot just lost power + print("power lost"); + apInit(); + # note: all button and knobs disabled in functions below + } + lastValue = newValue; + inrange0 = getprop("/instrumentation/nav[0]/in-range"); + # Shut off autopilot if HDG switch on and mode != 2 when NAV flag is on + if ( !inrange0 ) { + if ( hdgControl.getValue() and (modeControl.getValue() != 2)) { + rollControl.setDoubleValue(0.0); + apRollControl(); + } + } + settimer(apPower, 0.5); +} + +apRollControl = func { + + if (rollControl.getValue() ) { + if (hdgControl.getValue() ) { + ## + # hdg switch already on so check which roll mode is set + ## + apModeControlsSet(); + } else { + ## + # roll switch on and hdg switch off + ## + rollButton(1); + } + } else { + # A/P on/off switch was turned off, so turn off other AP switches + hdgControl.setDoubleValue(0.0); #hdgButton(0); +# rollButton(0); + apInit(); + } +} + + +apHdgControl = func { + + if (hdgControl.getValue() ) { + ## + # hdg switch is on so if roll switch is also on, check which roll mode is set + ## + if (rollControl.getValue() ) { + apModeControlsSet(); + } + } else { + # hdg switch turned off + hdgControl.setDoubleValue(0.0); hdgButton(0); + } +} + + +rollKnobUpdate = func { + if ( rollControl.getValue() and !hdgControl.getValue() ) { + settingTargetRollDeg.setDoubleValue( settingRollKnobDeg.getValue() ); + } +} + + +apModeControlsChange = func { + ## + # Delay mode change to allow time for multi-mode rotation + ## + settimer(apModeControlsSet, 2); +} + +apModeControlsSet = func { + newMode = modeControl.getValue(); + + oldMode = newMode; + + #All modes entered from hdg mode + if ( hdgControl.getValue() ) { + hdgButton(1); + if (newMode == 0 ){ + navButton(); + } elsif (newMode == 1 ) { + omniButton(); + } elsif (newMode == 3 ) { + aprButton(); + } elsif(newMode == 4 ) { + revButton(); + } + } else { + return; + } +} + + +rollButton = func(switch_on) { + ##print("rollButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if ( switch_on ) { + ## + # Engage the autopilot in Wings level mode (ROL) and set the turn rate + # from the "ROLL Knob". + ## + + lockAprHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["ROL"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } else { + lockAprHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(0); + lockRollMode.setIntValue(rollModes["OFF"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + + +hdgButton = func(switch_on) { + ##print("hdgButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if (switch_on) { + ## + # Engage the heading mode (HDG). + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["HDG"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + + settingTargetInterceptAngle.setDoubleValue(0.0); + + } else { + lockHdgHold.setBoolValue(0); + rollKnobUpdate(); + if ( rollControl.getValue() ) { + lockRollMode.setIntValue(rollModes["ROL"]); + } else { + lockRollMode.setIntValue(rollModes["OFF"]); + } + } +} + + +navButton = func { + ##print("navButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". The DG Course Selector should be set to the OBS "to" or + # "from" bearing. + # Set up NAV mode and switch to the 45 degree angle intercept NAV mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["NAV"]); + lockRollMode.setIntValue(rollModes["NAV"]); + + navArmFromHdg(); +} + +navArmFromHdg = func +{ + ## + # Abort the NAV-ARM mode if something has changed the arm mode to something + # else than NAV-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["NAV"]) + { + return; + } + + ## + # Activate the nav-hold controller and check the needle deviation. + ## + lockNavHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 9.95 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 9.95) + { + #print("deviation"); + settimer(navArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 10 degrees turn off the NAV-ARM. End of NAV-ARM sequence. + ## + elsif (abs(deviation) < 10.0) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + + +omniButton = func { + ##print("navButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". The DG Course Selector should be set to the OBS "to" or + # "from" bearing. + # Set up OMNI mode and switch to the 45 degree angle intercept OMNI mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["OMNI"]); + lockRollMode.setIntValue(rollModes["OMNI"]); + + omniArmFromHdg(); +} + + +omniArmFromHdg = func +{ + ## + # Abort the OMNI-ARM mode if something has changed the arm mode to something + # else than OMNI-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["OMNI"]) + { + return; + } + + ## + # Activate the omni-hold controller and check the needle deviation. + ## + lockOmniHold.setBoolValue(1); + deviation = getprop(filteredHeadingNeedleDeflection); + ## + # If the deflection is more than 9.95 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 9.95) + { + #print("deviation"); + settimer(omniArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 10 degrees turn off the OMNI-ARM. End of OMNI-ARM sequence. + ## + elsif (abs(deviation) < 10.0) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + +aprButton = func { + ##print("aprButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". Set the DG Course Selector to the LOC inbound heading. + # Set up APR mode and switch to the 45 degree angle intercept APR mode + ## + lockAprHold.setBoolValue(1); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["APR"]); + lockRollMode.setIntValue(rollModes["APR"]); + + aprArmFromHdg(); +} + +aprArmFromHdg = func +{ + ## + # Abort the APR-ARM mode if something has changed the arm mode to something + # else than APR-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["APR"]) + { + return; + } + + ## + # Activate the apr-hold controller and check the needle deviation. + ## + lockAprHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 2.5 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 2.495) + { + #print("deviation"); + settimer(aprArmFromHdg, 5); + return; + } +} + + +revButton = func { + ##print("revButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". Set the DG Course Selector to the LOC outbound + # (or reverse) heading. + # Set up REV mode and switch to the 45 degree angle intercept REV mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["REV"]); + + revArmFromHdg(); +} + + +revArmFromHdg = func +{ + ## + # Abort the REV-ARM mode if something has changed the arm mode to something + # else than REV-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["REV"]) + { + return; + } + + ## + # Activate the rev-hold controller and check the needle deviation. + ## + lockRevHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 2.5 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 2.495) + { + #print("deviation"); + settimer(revArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 2.5 - End of REV-ARM sequence. + ## + elsif (abs(deviation) < 2.5) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(1); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["REV"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + +touchPower = func{ + setprop(power,apVolts); +} + +apVolts = getprop(power); + +if ( apVolts == nil or apVolts < minVoltageLimit ) { + # Wait for autopilot to be powered up + var L = setlistener(power, func { + apPower(); + removelistener(L); + }); +} else { + # Skip the setlistener since autopilot is already powered up + settimer(touchPower ,10); + apPower(); +} + + diff --git a/Aircraft/Generic/century3.nas b/Aircraft/Generic/century3.nas new file mode 100644 index 000000000..684020371 --- /dev/null +++ b/Aircraft/Generic/century3.nas @@ -0,0 +1,737 @@ +## +# Century III Autopilot System +# Tries to behave like the Century III autopilot +# two axis +# +# One would also need the autopilot configuration file +# CENTURYIII.xml and the panel instrument configuration file +# +# Written by Dave Perry to match functionality described in +# +# CENTURY III +# AUTOPILOT FLIGHT SYSTEM +# PILOT'S OPERATING HANDBOOK +# NOVEMBER 1998 68S25 +# +# Draws heavily from the kap140 system written by Roy Vegard Ovesen +## + +# Properties + +locks = "/autopilot/CENTURYIII/locks"; +settings = "/autopilot/CENTURYIII/settings"; +internal = "/autopilot/internal"; +flightControls = "/controls/flight"; +autopilotControls = "/autopilot/CENTURYIII/controls"; + +# locks +propLocks = props.globals.getNode(locks, 1); + +lockAltHold = propLocks.getNode("alt-hold", 1); +lockPitchHold = propLocks.getNode("pitch-hold", 1); +lockAprHold = propLocks.getNode("apr-hold", 1); +lockGsHold = propLocks.getNode("gs-hold", 1); +lockHdgHold = propLocks.getNode("hdg-hold", 1); +lockNavHold = propLocks.getNode("nav-hold", 1); +lockOmniHold = propLocks.getNode("omni-hold", 1); +lockRevHold = propLocks.getNode("rev-hold", 1); +lockRollAxis = propLocks.getNode("roll-axis", 1); +lockRollMode = propLocks.getNode("roll-mode", 1); +lockPitchAxis = propLocks.getNode("pitch-axis", 1); +lockPitchMode = propLocks.getNode("pitch-mode", 1); +lockRollArm = propLocks.getNode("roll-arm", 1); +lockPitchArm = propLocks.getNode("pitch-arm", 1); + + +rollModes = { "OFF" : 0, "ROL" : 1, "HDG" : 2, "OMNI" : 3, "NAV" : 4, "REV" : 5, "APR" : 6 }; +pitchModes = { "OFF" : 0, "VS" : 1, "ALT" : 2, "GS" : 3, "AOA" : 4 }; +rollArmModes = { "OFF" : 0, "NAV" : 1, "OMNI" : 2, "APR" : 3, "REV" : 4 }; +pitchArmModes = { "OFF" : 0, "ALT" : 1, "GS" : 2 }; + +# settings +propSettings = props.globals.getNode(settings, 1); + +settingTargetAltPressure = propSettings.getNode("target-alt-pressure", 1); +settingTargetInterceptAngle = propSettings.getNode("target-intercept-angle", 1); +settingTargetPressureRate = propSettings.getNode("target-pressure-rate", 1); +settingTargetRollDeg = propSettings.getNode("target-roll-deg", 1); +settingRollKnobDeg = propSettings.getNode("roll-knob-deg", 1); +settingTargetPitchDeg = propSettings.getNode("target-pitch-deg", 1); +settingPitchWheelDeg = propSettings.getNode("pitch-wheel-deg", 1); +settingAutoPitchTrim = propSettings.getNode("auto-pitch-trim", 1); +settingGScaptured = propSettings.getNode("gs-captured", 1); +settingDeltaPitch = propSettings.getNode("delta-pitch", 1); + +#Flight controls +propFlightControls = props.globals.getNode(flightControls, 1); + +elevatorControl = propFlightControls.getNode("elevator", 1); +elevatorTrimControl = propFlightControls.getNode("elevator-trim", 1); + +#Autopilot controls +propAutopilotControls = props.globals.getNode(autopilotControls, 1); + +rollControl = propAutopilotControls.getNode("roll", 1); +# values 0 (ROLL switch off) 1 (ROLL switch on) + +hdgControl = propAutopilotControls.getNode("hdg", 1); +# values 0 (HDG switch off) 1 (HDG switch on) + +modeControl = propAutopilotControls.getNode("mode", 1); + +altControl = propAutopilotControls.getNode("alt", 1); +# values 0 (ALT switch off) 1 (ALT switch on) + +pitchControl = propAutopilotControls.getNode("pitch", 1); +# values 0 (PITCH switch off) 1 (PITCH switch on) + +headingNeedleDeflection = "/instrumentation/nav/heading-needle-deflection"; +gsNeedleDeflection = "/instrumentation/nav/gs-needle-deflection"; +indicatedPitchDeg = "/instrumentation/attitude-indicator/indicated-pitch-deg"; +staticPressure = "/systems/static/pressure-inhg"; +altitudePressure = "/autopilot/CENTURYIII/settings/target-alt-pressure"; +power="/systems/electrical/outputs/autopilot"; +enableAutoTrim = "/sim/model/enable-auto-trim"; +filteredHeadingNeedleDeflection = "/autopilot/internal/filtered-heading-needle-deflection"; + +pressureUnits = { "inHg" : 0, "hPa" : 1 }; +altPressure = 0.0; +gsTimeCheck = 0.0; +valueTest = 0; +lastValue = 0; +newValue = 0; +minVoltageLimit = 8.0; +oldMode = 2; +rollControl.setDoubleValue(0.0); +hdgControl.setDoubleValue(0.0); +altControl.setDoubleValue(0.0); +pitchControl.setDoubleValue(0.0); +modeControl.setDoubleValue(2.0); +settingTargetPitchDeg.setDoubleValue(0.0); +settingPitchWheelDeg.setDoubleValue(0.0); +settingDeltaPitch.setDoubleValue(0.0); +settingTargetPressureRate.setDoubleValue(0.0); +settingGScaptured.setDoubleValue(0.0); +# If you need to be able to enable/disable auto trim, make is a menue toggle. +# Auto trim enabled by default +setprop(enableAutoTrim, 1); +autoPitchTrim = 0.0; + +apInit = func { + ##print("ap init"); + + ## + # Initialises the autopilot. + ## + + lockAltHold.setBoolValue(0); + lockAprHold.setBoolValue(0); + lockGsHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(0); + lockRollMode.setIntValue(rollModes["OFF"]); + lockPitchAxis.setBoolValue(0); + lockPitchHold.setBoolValue(0); + lockPitchMode.setIntValue(pitchModes["OFF"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + lockPitchArm.setIntValue(pitchArmModes["OFF"]); +# Reset the memory for power down or power up + settingTargetAltPressure.setDoubleValue(0.0); + settingTargetPitchDeg.setDoubleValue(0.0); + settingTargetPressureRate.setDoubleValue(0.0); + settingTargetInterceptAngle.setDoubleValue(0.0); + settingTargetRollDeg.setDoubleValue(0.0); + settingAutoPitchTrim.setDoubleValue(0.0); + settingGScaptured.setDoubleValue(0.0); + settingRollKnobDeg.setDoubleValue(0.0); + +} + +apPower = func { + +## Monitor autopilot power +## Call apInit if the power is too low + + if (getprop(power) < minVoltageLimit) { + newValue = 0; + } else { + newValue = 1; + } + + valueTest = newValue - lastValue; +# print("v_test = ", v_test); + if (valueTest > 0.5) { + # autopilot just powered up + print("power up"); + apInit(); + } elsif (valueTest < -0.5) { + # autopilot just lost power + print("power lost"); + apInit(); + # note: all button and knobs disabled in functions below + } + lastValue = newValue; + + # Update difference between pitch wheel target and indicated pitch. + # Used to animate the Pitch Trim meter to the left of pitch wheel + if (rollControl.getValue() ) { + settingDeltaPitch.setDoubleValue(settingPitchWheelDeg.getValue() + - getprop(indicatedPitchDeg)); + } else { + settingDeltaPitch.setDoubleValue(0.0); + } + inrange0 = getprop("/instrumentation/nav[0]/in-range"); + # Shut off autopilot if HDG switch on and mode != 2 when NAV flag is on + if ( !inrange0 ) { + if ( hdgControl.getValue() and (modeControl.getValue() != 2)) { + rollControl.setDoubleValue(0.0); + apRollControl(); + } + } + settimer(apPower, 0.5); +} + +apRollControl = func { + + if (rollControl.getValue() ) { + rollButton(1); + } else { + # A/P on/off switch was turned off, so turn off other AP switches + hdgControl.setDoubleValue(0.0); #hdgButton(0); + altControl.setDoubleValue(0.0); #altButton(0); + pitchControl.setDoubleValue(0.0); #pitchButton(0); +# rollButton(0); + apInit(); + } +} + +apHdgControl = func { + + if (hdgControl.getValue() ) { + # hdg switch turned on sets roll + rollControl.setDoubleValue(1.0); + rollButton(1); + ## + # hdg switch is on so check which roll mode is set + ## + apModeControlsSet(); + } else { + # hdg switch turned off resets alt and pitch + hdgControl.setDoubleValue(0.0); hdgButton(0); + altControl.setDoubleValue(0.0); altButton(0); + pitchControl.setDoubleValue(0.0); pitchButton(0); + } +} + +apAltControl = func { + + if ( altControl.getValue() ){ + # Alt switch on so set ROLL, HDG, and PITCH + rollControl.setDoubleValue(1.0); + rollButton(1); + hdgControl.setDoubleValue(1.0); + # roll and hdg switches on so check which roll mode is set + apModeControlsSet(); + pitchControl.setDoubleValue(1.0); + pitchButton(1); + altButton(1); + } else { + altButton(0); + } +} + +apPitchControl = func { + + if ( pitchControl.getValue() ) { + # Pitch switch on so set ROLL and HDG + rollControl.setDoubleValue(1.0); + rollButton(1); + hdgControl.setDoubleValue(1.0); + # roll and hdg switches on so check which roll mode is set + apModeControlsSet(); + pitchButton(1); + } else { + altControl.setDoubleValue(0.0); + altButton(0); + pitchButton(0); + } +} + +rollKnobUpdate = func { + if ( rollControl.getValue() and !hdgControl.getValue() ) { + settingTargetRollDeg.setDoubleValue( settingRollKnobDeg.getValue() ); + } +} + + +pitchWheelUpdate = func { + if ( rollControl.getValue() and !altControl.getValue() ) { + settingTargetPitchDeg.setDoubleValue( settingPitchWheelDeg.getValue() ); + } +} + + +apModeControlsChange = func { + ## + # Delay mode change to allow time for multi-mode rotation + ## + settimer(apModeControlsSet, 2); +} + +apModeControlsSet = func { + newMode = modeControl.getValue(); + + ## + # Decouple GS if the mode selector is switched from LOC NORM + ## + if (oldMode == rollModes["APR"] and newMode != rollModes["APR"]) + { + if (lockPitchMode.getValue() == pitchModes["GS"]) + { + lockPitchMode.setIntValue(pitchModes["OFF"]); + } + if (lockPitchArmModes.getValue() == pitchArmModes["GS"]) + { + lockPitchArmMode.setIntValue(pitchModes["OFF"]); + } + lockGsHold.setBoolValue(0); + settingGScoupled.setDoubleValue(0.0); + } + + oldMode = newMode; + + #All modes entered from hdg mode + if ( hdgControl.getValue() ) { + hdgButton(1); + if (newMode == 0 ){ + navButton(); + } elsif (newMode == 1 ) { + omniButton(); + } elsif (newMode == 3 ) { + aprButton(); + } elsif(newMode == 4 ) { + revButton(); + } + } else { + return; + } +} + +rollButton = func(switch_on) { + ##print("rollButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if ( switch_on ) { + ## + # Engage the autopilot in Wings level mode (ROL) and set the turn rate + # from the "ROLL Knob". + ## + + lockAprHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["ROL"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } else { + lockAprHold.setBoolValue(0); + lockHdgHold.setBoolValue(0); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockRollAxis.setBoolValue(0); + lockRollMode.setIntValue(rollModes["OFF"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + + +hdgButton = func(switch_on) { + ##print("hdgButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if (switch_on) { + ## + # Engage the heading mode (HDG). + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["HDG"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + + settingTargetInterceptAngle.setDoubleValue(0.0); + + } else { + lockHdgHold.setBoolValue(0); + rollKnobUpdate(); + if ( rollControl.getValue() ) { + lockRollMode.setIntValue(rollModes["ROL"]); + } else { + lockRollMode.setIntValue(rollModes["OFF"]); + } + } +} + +navButton = func { + ##print("navButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". The DG Course Selector should be set to the OBS "to" or + # "from" bearing. + # Set up NAV mode and switch to the 45 degree angle intercept NAV mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["NAV"]); + lockRollMode.setIntValue(rollModes["NAV"]); + + navArmFromHdg(); +} + +navArmFromHdg = func +{ + ## + # Abort the NAV-ARM mode if something has changed the arm mode to something + # else than NAV-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["NAV"]) + { + return; + } + + ## + # Activate the nav-hold controller and check the needle deviation. + ## + lockNavHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 9.95 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 9.95) + { + #print("deviation"); + settimer(navArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 10 degrees turn off the NAV-ARM. End of NAV-ARM sequence. + ## + elsif (abs(deviation) < 10.0) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + +omniButton = func { + ##print("navButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". The DG Course Selector should be set to the OBS "to" or + # "from" bearing. + # Set up OMNI mode and switch to the 45 degree angle intercept OMNI mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["OMNI"]); + lockRollMode.setIntValue(rollModes["OMNI"]); + + omniArmFromHdg(); +} + + +omniArmFromHdg = func +{ + ## + # Abort the OMNI-ARM mode if something has changed the arm mode to something + # else than OMNI-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["OMNI"]) + { + return; + } + + ## + # Activate the omni-hold controller and check the needle deviation. + ## + lockOmniHold.setBoolValue(1); + deviation = getprop(filteredHeadingNeedleDeflection); + ## + # If the deflection is more than 9.95 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 9.95) + { + #print("deviation"); + settimer(omniArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 10 degrees turn off the OMNI-ARM. End of OMNI-ARM sequence. + ## + elsif (abs(deviation) < 10.0) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + + +aprButton = func { + ##print("aprButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". Set the DG Course Selector to the LOC inbound heading. + # Set up APR mode and switch to the 45 degree angle intercept APR mode + ## + lockAprHold.setBoolValue(1); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["APR"]); + lockRollMode.setIntValue(rollModes["APR"]); + gsTimeCheck = -1; + + aprArmFromHdg(); +} + +aprArmFromHdg = func +{ + ## + # Abort the APR-ARM mode if something has changed the arm mode to something + # else than APR-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["APR"] + or !lockAltHold.getValue() + or getprop(gsNeedleDeflection) < 0.0) + { + return; + } + gsTimeCheck = gsTimeCheck + 1; + if (gsTimeCheck < 20) + { + settimer(aprArmFromHdg, 1.0); + } + + ## + # Activate the apr-hold controller and check the needle deviation. + ## + lockAprHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 2.5 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 2.495) + { + #print("deviation"); + settimer(aprArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 2.5 degrees, start the GS-ARM sequence + ## + elsif (abs(deviation) < 2.5) + { + lockPitchArm.setIntValue(pitchArmModes["GS"]); + gsArm(); + } +} + +gsArm = func { + ## + # Abort the GS-ARM mode if something has changed the arm mode to something + # else than GS-ARM. + ## + if (lockPitchArm.getValue() != pitchArmModes["GS"]) + { + return; + } + + deviation = getprop(gsNeedleDeflection); + ## + # If the deflection is more than 0.25 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 0.25) + { + #print("deviation"); + settimer(gsArm, 5); + return; + } + ## + # If the deviation is less than 1 then activate the GS pitch mode. + ## + elsif (abs(deviation) < 0.251) + { + #print("capture"); + lockAltHold.setBoolValue(0); + lockGsHold.setBoolValue(1); + lockPitchMode.setIntValue(pitchModes["GS"]); + lockPitchArm.setIntValue(pitchArmModes["OFF"]); + settingGScaptured.setDoubleValue(1.0); + } +} + + +revButton = func { + ##print("revButton"); +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + ## + # The Mode Selector and DG Course Selector should be set before switching the HDG + # rocker switch to "on". Set the DG Course Selector to the LOC outbound + # (or reverse) heading. + # Set up REV mode and switch to the 45 degree angle intercept REV mode + ## + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(0); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollArm.setIntValue(rollArmModes["REV"]); + + revArmFromHdg(); +} + + +revArmFromHdg = func +{ + ## + # Abort the REV-ARM mode if something has changed the arm mode to something + # else than REV-ARM. + ## + if (lockRollArm.getValue() != rollArmModes["REV"]) + { + return; + } + + ## + # Activate the rev-hold controller and check the needle deviation. + ## + lockRevHold.setBoolValue(1); + deviation = getprop(headingNeedleDeflection); + ## + # If the deflection is more than 2.5 degrees wait 5 seconds and check again. + ## + if (abs(deviation) > 2.495) + { + #print("deviation"); + settimer(revArmFromHdg, 5); + return; + } + ## + # If the deviation is less than 2.5 - End of REV-ARM sequence. + ## + elsif (abs(deviation) < 2.5) + { + #print("capture"); + lockRollArm.setIntValue(rollArmModes["OFF"]); + lockAprHold.setBoolValue(0); + lockRevHold.setBoolValue(1); + lockHdgHold.setBoolValue(1); + lockNavHold.setBoolValue(0); + lockOmniHold.setBoolValue(0); + lockRollAxis.setBoolValue(1); + lockRollMode.setIntValue(rollModes["REV"]); + lockRollArm.setIntValue(rollArmModes["OFF"]); + } +} + + +altButton = func(switch_on) { +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if (switch_on) { + lockAltHold.setBoolValue(1); + lockPitchAxis.setBoolValue(1); +# lockPitchMode.setIntValue(pitchModes["ALT"]); + + altPressure = getprop(staticPressure); + settingTargetAltPressure.setDoubleValue(altPressure); +# print("enableAutoTrim = ", getprop(enableAutoTrim)); + if ( getprop(enableAutoTrim) ) { + settingAutoPitchTrim.setDoubleValue(1); + } + } else { + lockAltHold.setBoolValue(0); + lockPitchAxis.setBoolValue(0); + lockPitchMode.setIntValue(pitchModes["OFF"]); + lockPitchArm.setIntValue(pitchArmModes["OFF"]); + pitchWheelUpdate(); + settingTargetPressureRate.setDoubleValue(0.0); + # alt switch is off so make sure the glide slope is disabled + settingGScaptured.setDoubleValue(0.0); + lockGsHold.setBoolValue(0); + } +} + +pitchButton = func(switch_on) { +# Disable button if too little power + if (getprop(power) < minVoltageLimit) { return; } + + if (switch_on) { + lockPitchHold.setBoolValue(1); +# lockPitchAxis.setBoolValue(1); +# lockPitchMode.setIntValue(pitchModes["AOA"]); +# print("enableAutoTrim = ", getprop(enableAutoTrim)); + if ( getprop(enableAutoTrim) ) { + settingAutoPitchTrim.setDoubleValue(1); + } + } else { + lockPitchHold.setBoolValue(0); + lockPitchAxis.setBoolValue(0); + lockPitchMode.setIntValue(pitchModes["OFF"]); + settingAutoPitchTrim.setDoubleValue(0); + } +} + +touchPower = func{ + setprop(power,apVolts); +} + +apVolts = getprop(power); + +if ( apVolts == nil or apVolts < minVoltageLimit ) { + # Wait for autopilot to be powered up + var L = setlistener(power, func { + apPower(); + removelistener(L); + }); +} else { + # Skip the setlistener since autopilot is already powered up + settimer(touchPower ,10); + apPower(); +} + +