diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index ff78f885e4e..44c33ca1768 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -46,6 +46,7 @@ 1. [AUTOFLIGHT] Fixed managed speed not engaging when V2 is confirmed after a departure runway change - @tracernz (Mi 1. [GSX/EFB] FBW Chocks & Cones are usable with GSX Fuel/Payload Sync and react to GSX Pushback - @Fragtality (Fragtality) 1. [GSX] Fixed GSX pin not actually disabling NWS - @Maximilian-Reuter (\_Chaoz_) +1. [EFB/FBW] Added option for TOGA off axis for devices where the TOGA button is built into the throttle - @ImmortalCake ## 0.11.0 diff --git a/fbw-a32nx/src/localization/flypad/en.json b/fbw-a32nx/src/localization/flypad/en.json index 08b973163aa..ca600ddc6f4 100644 --- a/fbw-a32nx/src/localization/flypad/en.json +++ b/fbw-a32nx/src/localization/flypad/en.json @@ -629,6 +629,7 @@ "ReverseFull": "Reverse Full", "ReverseIdle": "Reverse Idle", "ReverserOnAxis": "Reverser On Axis", + "TogaOnAxis": "TOGA On Axis", "SaveAndApply": "Save and Apply", "SetFromThrottle": "Set from Throttle", "ThrottleConfigurationReset": "Throttle Configuration Reset" diff --git a/fbw-a32nx/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx b/fbw-a32nx/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx index 77a7d36e691..74dff22b4ca 100644 --- a/fbw-a32nx/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx +++ b/fbw-a32nx/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx @@ -32,6 +32,9 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { const [reverserOnAxis1, setReverserOnAxis1] = useSimVar('L:A32NX_THROTTLE_MAPPING_USE_REVERSE_ON_AXIS:1', 'number', 1000); const [, setReverserOnAxis2] = useSimVar('L:A32NX_THROTTLE_MAPPING_USE_REVERSE_ON_AXIS:2', 'number', 1000); + const [togaOnAxis1, setTogaOnAxis1] = useSimVar('L:A32NX_THROTTLE_MAPPING_USE_TOGA_ON_AXIS:1', 'number', 1000); + const [, setTogaOnAxis2] = useSimVar('L:A32NX_THROTTLE_MAPPING_USE_TOGA_ON_AXIS:2', 'number', 1000); + const [, syncToDisk] = useSimVar('K:A32NX.THROTTLE_MAPPING_SAVE_TO_FILE', 'number', 1000); const [, defaultsToThrottle] = useSimVar('K:A32NX.THROTTLE_MAPPING_SET_DEFAULTS', 'number', 100); const [, syncToThrottle] = useSimVar('K:A32NX.THROTTLE_MAPPING_LOAD_FROM_FILE', 'number', 100); @@ -76,15 +79,18 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { if (reverserOnAxis1 === 0 && selectedIndex < 2) { setSelectedIndex(2); } + if (togaOnAxis1 === 0 && selectedIndex > 4) { + setSelectedIndex(4); + } }, [reverserOnAxis1, selectedIndex]); const getOverlapErrors = (mappingsAxis: ThrottleSimvar[]) => { const overlapErrors: string[] = []; - for (let index = reverserOnAxis1 ? 0 : 2; index < mappingsAxis.length; index++) { + for (let index = reverserOnAxis1 ? 0 : 2; index < (togaOnAxis1 ? mappingsAxis.length : mappingsAxis.length - 1); index++) { const element = mappingsAxis[index]; - for (let nextIndex = index + 1; nextIndex < mappingsAxis.length; nextIndex++) { + for (let nextIndex = index + 1; nextIndex < (togaOnAxis1 ? mappingsAxis.length : mappingsAxis.length - 1); nextIndex++) { const nextElement = mappingsAxis[nextIndex]; if (element.getHiGetter() >= nextElement.getLowGetter() || element.getLowGetter() >= nextElement.getHiGetter()) { overlapErrors.push(`${element.readableName} (${element.getLowGetter().toFixed(2)}) ${t('Settings.ThrottleConfig.ErrorOverlapMsg')} ${nextElement.readableName} (${nextElement.getLowGetter().toFixed(2)})`); @@ -110,6 +116,14 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { } }; + const setTogaOnAxis = (togaOnAxis: number) => { + setTogaOnAxis1(togaOnAxis); + setTogaOnAxis2(togaOnAxis); + if (togaOnAxis === 0 && selectedIndex > 4) { + setSelectedIndex(4); + } + }; + const switchDetent = (index: number) => { if (index >= 0 && index <= 5) { setSelectedIndex(index); @@ -118,7 +132,18 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { const navigationBar = ( - switchDetent(5)} selected={selectedIndex === 5}>TO/GA + { + if (togaOnAxis1) { + switchDetent(5); + } + }} + selected={selectedIndex === 5} + > + TO/GA + switchDetent(4)} selected={selectedIndex === 4}>FLX switchDetent(3)} selected={selectedIndex === 3}>CLB switchDetent(2)} selected={selectedIndex === 2}>Idle @@ -263,6 +288,10 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => {
+
+
{t('Settings.ThrottleConfig.TogaOnAxis')}
+ setTogaOnAxis(value ? 1 : 0)} /> +
{t('Settings.ThrottleConfig.ReverserOnAxis')}
setReversersOnAxis(value ? 1 : 0)} /> diff --git a/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.cpp b/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.cpp index 811f9abb6fd..23bae5a3c85 100644 --- a/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.cpp +++ b/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.cpp @@ -16,6 +16,7 @@ ThrottleAxisMapping::ThrottleAxisMapping(unsigned int id) { LVAR_THRUST_LEVER_ANGLE = LVAR_THRUST_LEVER_ANGLE.append(stringId); LVAR_LOAD_CONFIG = LVAR_LOAD_CONFIG.append(stringId); LVAR_USE_REVERSE_ON_AXIS = LVAR_USE_REVERSE_ON_AXIS.append(stringId); + LVAR_USE_TOGA_ON_AXIS = LVAR_USE_TOGA_ON_AXIS.append(stringId); LVAR_DETENT_REVERSE_LOW = LVAR_DETENT_REVERSE_LOW.append(stringId); LVAR_DETENT_REVERSE_HIGH = LVAR_DETENT_REVERSE_HIGH.append(stringId); LVAR_DETENT_REVERSEIDLE_LOW = LVAR_DETENT_REVERSEIDLE_LOW.append(stringId); @@ -34,6 +35,7 @@ ThrottleAxisMapping::ThrottleAxisMapping(unsigned int id) { idThrustLeverAngle = std::make_unique(LVAR_THRUST_LEVER_ANGLE.c_str()); idUsingConfig = std::make_unique(LVAR_LOAD_CONFIG.c_str()); idUseReverseOnAxis = std::make_unique(LVAR_USE_REVERSE_ON_AXIS.c_str()); + idUseTogaOnAxis = std::make_unique(LVAR_USE_TOGA_ON_AXIS.c_str()); idIncrementNormal = std::make_unique(LVAR_INCREMENT_NORMAL.c_str()); idIncrementSmall = std::make_unique(LVAR_INCREMENT_SMALL.c_str()); idDetentReverseLow = std::make_unique(LVAR_DETENT_REVERSE_LOW.c_str()); @@ -143,10 +145,14 @@ void ThrottleAxisMapping::onEventThrottleSet(long value) { if (!useReverseOnAxis && !isReverseToggleActive) { isReverseToggleKeyActive = false; } + if (!useTogaOnAxis) { + isTogaActive = false; + } setCurrentValue(value / 16384.0); } void ThrottleAxisMapping::onEventThrottleFull() { + isTogaActive = true; setCurrentValue(1.0); } @@ -157,10 +163,20 @@ void ThrottleAxisMapping::onEventThrottleCut() { } void ThrottleAxisMapping::onEventThrottleIncrease() { + if (!useTogaOnAxis && currentValue == 1.0) { + // Specific binding for activating TO/GA when not on axis. + isTogaActive = true; + } increaseThrottleBy(incrementNormal); } void ThrottleAxisMapping::onEventThrottleIncreaseSmall() { + if (!useTogaOnAxis) { + // Specific binding for deactivating TO/GA when not on axis. + // Not using onEventThrottleDecrease because of a bug in MSFS preventing + // use of a key on press and a key on release for the same function. + isTogaActive = false; + } increaseThrottleBy(incrementSmall); } @@ -231,6 +247,8 @@ void ThrottleAxisMapping::setCurrentValue(double value) { double newTLA = 0; if (!useReverseOnAxis && (isReverseToggleActive || isReverseToggleKeyActive)) { newTLA = (TLA_REVERSE / 2.0) * (value + 1.0); + } else if (!useTogaOnAxis && isTogaActive) { + newTLA = TLA_TOGA; } else { newTLA = thrustLeverAngleMapping.get(value); } @@ -280,6 +298,7 @@ void ThrottleAxisMapping::decreaseThrottleBy(double value) { ThrottleAxisMapping::Configuration ThrottleAxisMapping::getDefaultConfiguration() { return { true, // use reverse on axis + true, // use toga on axis 0.05, // increment normal 0.025, // increment small -1.00, // reverse low @@ -299,14 +318,15 @@ ThrottleAxisMapping::Configuration ThrottleAxisMapping::getDefaultConfiguration( ThrottleAxisMapping::Configuration ThrottleAxisMapping::loadConfigurationFromLocalVariables() { idUsingConfig->set(true); - return {idUseReverseOnAxis->get() == 1, idIncrementNormal->get(), idIncrementSmall->get(), idDetentReverseLow->get(), - idDetentReverseHigh->get(), idDetentReverseIdleLow->get(), idDetentReverseIdleHigh->get(), idDetentIdleLow->get(), - idDetentIdleHigh->get(), idDetentClimbLow->get(), idDetentClimbHigh->get(), idDetentFlexMctLow->get(), - idDetentFlexMctHigh->get(), idDetentTogaLow->get(), idDetentTogaHigh->get()}; + return {idUseReverseOnAxis->get() == 1, idUseTogaOnAxis->get() == 1, idIncrementNormal->get(), idIncrementSmall->get(), + idDetentReverseLow->get(), idDetentReverseHigh->get(), idDetentReverseIdleLow->get(), idDetentReverseIdleHigh->get(), + idDetentIdleLow->get(), idDetentIdleHigh->get(), idDetentClimbLow->get(), idDetentClimbHigh->get(), + idDetentFlexMctLow->get(), idDetentFlexMctHigh->get(), idDetentTogaLow->get(), idDetentTogaHigh->get()}; } void ThrottleAxisMapping::storeConfigurationInLocalVariables(const Configuration& configuration) { idUseReverseOnAxis->set(configuration.useReverseOnAxis); + idUseTogaOnAxis->set(configuration.useTogaOnAxis); idIncrementNormal->set(configuration.incrementNormal); idIncrementSmall->set(configuration.incrementSmall); if (configuration.useReverseOnAxis) { @@ -326,14 +346,20 @@ void ThrottleAxisMapping::storeConfigurationInLocalVariables(const Configuration idDetentClimbHigh->set(configuration.climbHigh); idDetentFlexMctLow->set(configuration.flxMctLow); idDetentFlexMctHigh->set(configuration.flxMctHigh); - idDetentTogaLow->set(configuration.togaLow); - idDetentTogaHigh->set(configuration.togaHigh); + if (configuration.useTogaOnAxis) { + idDetentTogaLow->set(configuration.togaLow); + idDetentTogaHigh->set(configuration.togaHigh); + } else { + idDetentTogaLow->set(0.0); + idDetentTogaHigh->set(0.0); + } } ThrottleAxisMapping::Configuration ThrottleAxisMapping::loadConfigurationFromIniStructure(const INIStructure& structure) { idUsingConfig->set(true); return { INITypeConversion::getBoolean(structure, CONFIGURATION_SECTION_COMMON, "REVERSE_ON_AXIS", false), + INITypeConversion::getBoolean(structure, CONFIGURATION_SECTION_COMMON, "TOGA_ON_AXIS", true), INITypeConversion::getDouble(structure, CONFIGURATION_SECTION_COMMON, "KEY_INCREMENT_NORMAL", 0.05), INITypeConversion::getDouble(structure, CONFIGURATION_SECTION_COMMON, "KEY_INCREMENT_SMALL", 0.025), INITypeConversion::getDouble(structure, CONFIGURATION_SECTION_AXIS, "REVERSE_LOW", -1.00), @@ -353,6 +379,7 @@ ThrottleAxisMapping::Configuration ThrottleAxisMapping::loadConfigurationFromIni void ThrottleAxisMapping::storeConfigurationInIniStructure(INIStructure& structure, const Configuration& configuration) { structure[CONFIGURATION_SECTION_COMMON]["REVERSE_ON_AXIS"] = configuration.useReverseOnAxis ? "true" : "false"; + structure[CONFIGURATION_SECTION_COMMON]["TOGA_ON_AXIS"] = configuration.useTogaOnAxis ? "true" : "false"; structure[CONFIGURATION_SECTION_COMMON]["KEY_INCREMENT_NORMAL"] = std::to_string(configuration.incrementNormal); structure[CONFIGURATION_SECTION_COMMON]["KEY_INCREMENT_SMALL"] = std::to_string(configuration.incrementSmall); structure[CONFIGURATION_SECTION_AXIS]["REVERSE_LOW"] = std::to_string(configuration.reverseLow); @@ -373,6 +400,9 @@ void ThrottleAxisMapping::updateMappingFromConfiguration(const Configuration& co // update use reverse on axis useReverseOnAxis = configuration.useReverseOnAxis; + // update use reverse on axis + useTogaOnAxis = configuration.useTogaOnAxis; + // update increments incrementNormal = configuration.incrementNormal; incrementSmall = configuration.incrementSmall; @@ -397,12 +427,14 @@ void ThrottleAxisMapping::updateMappingFromConfiguration(const Configuration& co // flex / mct mappingTable.emplace_back(configuration.flxMctLow, TLA_FLEX_MCT); mappingTable.emplace_back(configuration.flxMctHigh, TLA_FLEX_MCT); - // toga - mappingTable.emplace_back(configuration.togaLow, TLA_TOGA); - mappingTable.emplace_back(configuration.togaHigh, TLA_TOGA); + if (configuration.useTogaOnAxis) { + // toga + mappingTable.emplace_back(configuration.togaLow, TLA_TOGA); + mappingTable.emplace_back(configuration.togaHigh, TLA_TOGA); + } // update interpolation lookup table - thrustLeverAngleMapping.initialize(mappingTable, useReverseOnAxis ? TLA_REVERSE : TLA_IDLE, TLA_TOGA); + thrustLeverAngleMapping.initialize(mappingTable, useReverseOnAxis ? TLA_REVERSE : TLA_IDLE, useTogaOnAxis ? TLA_TOGA : TLA_FLEX_MCT); // remember idle setting idleValue = configuration.idleLow; diff --git a/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.h b/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.h index 22f60a911dc..7b22078c7c2 100644 --- a/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.h +++ b/fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.h @@ -50,6 +50,7 @@ class ThrottleAxisMapping { private: struct Configuration { bool useReverseOnAxis; + bool useTogaOnAxis; double incrementNormal; double incrementSmall; double reverseLow; @@ -85,12 +86,14 @@ class ThrottleAxisMapping { void decreaseThrottleBy(double value); bool useReverseOnAxis = false; + bool useTogaOnAxis = false; double incrementNormal = 0.0; double incrementSmall = 0.0; bool inFlight = false; bool isReverseToggleActive = false; bool isReverseToggleKeyActive = false; + bool isTogaActive = false; double idleValue = 0.0; double currentValue = 0.0; @@ -103,6 +106,7 @@ class ThrottleAxisMapping { std::unique_ptr idUsingConfig; std::unique_ptr idUseReverseOnAxis; + std::unique_ptr idUseTogaOnAxis; std::unique_ptr idIncrementNormal; std::unique_ptr idIncrementSmall; std::unique_ptr idDetentReverseLow; @@ -122,6 +126,7 @@ class ThrottleAxisMapping { std::string LVAR_THRUST_LEVER_ANGLE = "A32NX_AUTOTHRUST_TLA:"; std::string LVAR_LOAD_CONFIG = "A32NX_THROTTLE_MAPPING_LOADED_CONFIG:"; std::string LVAR_USE_REVERSE_ON_AXIS = "A32NX_THROTTLE_MAPPING_USE_REVERSE_ON_AXIS:"; + std::string LVAR_USE_TOGA_ON_AXIS = "A32NX_THROTTLE_MAPPING_USE_TOGA_ON_AXIS:"; std::string LVAR_INCREMENT_NORMAL = "A32NX_THROTTLE_MAPPING_INCREMENT_NORMAL"; std::string LVAR_INCREMENT_SMALL = "A32NX_THROTTLE_MAPPING_INCREMENT_SMALL"; std::string LVAR_DETENT_REVERSE_LOW = "A32NX_THROTTLE_MAPPING_REVERSE_LOW:";