Skip to content

Commit

Permalink
feat(efb/fbw): Support for TO/GA button built into the throttle (not …
Browse files Browse the repository at this point in the history
…on axis) (flybywiresim#8247)

* EFB and sim variables

* Activate TO/GA on full throttle key

* Change key mapping for TO/GA on/off

* Update CHANGELOG.md

* Localisation, proper terminology

* Make TOGA On Axis default true

* fix: changelog 0.12

* Update CHANGELOG.md
  • Loading branch information
ImmortalCake authored Jan 17, 2024
1 parent 87caf3b commit 91334d9
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 13 deletions.
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions fbw-a32nx/src/localization/flypad/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)})`);
Expand All @@ -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);
Expand All @@ -118,7 +132,18 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => {

const navigationBar = (
<VerticalSelectGroup>
<SelectItem onSelect={() => switchDetent(5)} selected={selectedIndex === 5}>TO/GA</SelectItem>
<SelectItem
disabled={!togaOnAxis1}
className={`${togaOnAxis1 ? '' : 'opacity-30'}`}
onSelect={() => {
if (togaOnAxis1) {
switchDetent(5);
}
}}
selected={selectedIndex === 5}
>
TO/GA
</SelectItem>
<SelectItem onSelect={() => switchDetent(4)} selected={selectedIndex === 4}>FLX</SelectItem>
<SelectItem onSelect={() => switchDetent(3)} selected={selectedIndex === 3}>CLB</SelectItem>
<SelectItem onSelect={() => switchDetent(2)} selected={selectedIndex === 2}>Idle</SelectItem>
Expand Down Expand Up @@ -263,6 +288,10 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => {
<div className="space-y-2">
<div>
<div className="flex flex-row justify-center items-center p-4 mt-auto mb-8 space-x-16 w-full rounded-lg border-2 border-theme-accent">
<div className="flex flex-row justify-center items-center space-x-4">
<div>{t('Settings.ThrottleConfig.TogaOnAxis')}</div>
<Toggle value={!!togaOnAxis1} onToggle={(value) => setTogaOnAxis(value ? 1 : 0)} />
</div>
<div className="flex flex-row justify-center items-center space-x-4">
<div>{t('Settings.ThrottleConfig.ReverserOnAxis')}</div>
<Toggle value={!!reverserOnAxis1} onToggle={(value) => setReversersOnAxis(value ? 1 : 0)} />
Expand Down
52 changes: 42 additions & 10 deletions fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -34,6 +35,7 @@ ThrottleAxisMapping::ThrottleAxisMapping(unsigned int id) {
idThrustLeverAngle = std::make_unique<LocalVariable>(LVAR_THRUST_LEVER_ANGLE.c_str());
idUsingConfig = std::make_unique<LocalVariable>(LVAR_LOAD_CONFIG.c_str());
idUseReverseOnAxis = std::make_unique<LocalVariable>(LVAR_USE_REVERSE_ON_AXIS.c_str());
idUseTogaOnAxis = std::make_unique<LocalVariable>(LVAR_USE_TOGA_ON_AXIS.c_str());
idIncrementNormal = std::make_unique<LocalVariable>(LVAR_INCREMENT_NORMAL.c_str());
idIncrementSmall = std::make_unique<LocalVariable>(LVAR_INCREMENT_SMALL.c_str());
idDetentReverseLow = std::make_unique<LocalVariable>(LVAR_DETENT_REVERSE_LOW.c_str());
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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),
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions fbw-common/src/wasm/fbw_common/src/ThrottleAxisMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ThrottleAxisMapping {
private:
struct Configuration {
bool useReverseOnAxis;
bool useTogaOnAxis;
double incrementNormal;
double incrementSmall;
double reverseLow;
Expand Down Expand Up @@ -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;
Expand All @@ -103,6 +106,7 @@ class ThrottleAxisMapping {

std::unique_ptr<LocalVariable> idUsingConfig;
std::unique_ptr<LocalVariable> idUseReverseOnAxis;
std::unique_ptr<LocalVariable> idUseTogaOnAxis;
std::unique_ptr<LocalVariable> idIncrementNormal;
std::unique_ptr<LocalVariable> idIncrementSmall;
std::unique_ptr<LocalVariable> idDetentReverseLow;
Expand All @@ -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:";
Expand Down

0 comments on commit 91334d9

Please sign in to comment.