Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(a380x/fws): Automatic normal checklist reset #9614

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
1. [A32NX] Fixed APU fire detection - @tracernz (Mike)
1. [A380X/COND] Fix wasm crash during rapid decompression - @mjuhe (Miquel Juhe)
1. [A380X] Fix EWD avail. thrust fill area & PFD rudder trim visibility on ground - @flogross89 (floridude)
1. [A380X/FWS] Add automatic normal checklists reset on powerup, go around & shutdown - @BravoMike99 (bruno_pt99)

## 0.12.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
//
// SPDX-License-Identifier: GPL-3.0

import {
AbnormalProcedure,
EcamAbnormalSensedProcedures,
isChecklistAction,
} from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages';
import { EcamAbnormalSensedProcedures } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages';
import {
MappedSubject,
Subject,
Expand Down Expand Up @@ -88,28 +84,6 @@ export class FwsAbnormalSensed {
}),
);
this.pub.pub('fws_abn_sensed_procedures', flattened, true);
SimVar.SetSimVarValue('L:A32NX_EWD_DEBUG_ABNORMAL', 'string', flattened[0] ? flattened[0].id : '');

console.log('%c------- ABN SENSED PROCEDURES -------', 'font-family:monospace; font-weight: bold');
// Debug output for ABN sensed procedures
this.fws.activeAbnormalSensedList.get().forEach((val, key) => {
const proc = EcamAbnormalSensedProcedures[key] as AbnormalProcedure;
console.log('%c' + proc.title, 'font-family:monospace; font-weight: bold');
proc.items.forEach((it, itemIdx) => {
if (val.itemsToShow[itemIdx]) {
const cpl = isChecklistAction(it)
? val.itemsChecked[itemIdx]
? it.labelNotCompleted
: ` .......... ${it.labelNotCompleted}`
: '';
console.log(
`%c${' '.repeat(it.level ?? 0)} ${val.itemsChecked[itemIdx] ? 'X' : 'O'} ${it.name} ${cpl} ${it.style ? `(${it.style})` : ''}`,
'font-family:monospace; font-weight: bold',
);
}
});
});
console.log('%c------- END -------', 'font-family:monospace; font-weight: bold');
},
true,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export class FwsCore {
/* PSEUDO FWC VARIABLES */
private readonly startupTimer = new DebounceTimer();

private readonly startupCompleted = Subject.create(false);
public readonly startupCompleted = Subject.create(false);

/** Keys/IDs of all failures currently active, irrespective they are already cleared or not */
public readonly allCurrentFailures: string[] = [];
Expand Down Expand Up @@ -567,7 +567,6 @@ export class FwsCore {
public readonly engine4Running = Subject.create(false);

public readonly allBatteriesOff = Subject.create(false);

/* 26 - FIRE */

public readonly fduDiscreteWord = Arinc429Register.empty();
Expand Down Expand Up @@ -1034,7 +1033,6 @@ export class FwsCore {
public readonly yellowElecAandBPumpOff = Subject.create(false);

/* 31 - FWS */

public readonly fwcFlightPhase = Subject.create(-1);

public readonly flightPhase128 = Subject.create(false);
Expand Down Expand Up @@ -1090,6 +1088,14 @@ export class FwsCore {

public readonly flightPhaseInhibitOverrideNode = new NXLogicMemoryNode(false);

public readonly manualCheckListReset = Subject.create(false);

private readonly phase12ShutdownMemoryNode = new NXLogicMemoryNode();

private readonly shutDownFor50MinutesClResetConfNode = new NXLogicConfirmNode(3000);

public readonly shutDownFor50MinutesCheckListReset = Subject.create(false);

/** If one of the ADR's CAS is above V1 - 4kts, confirm for 0.3s */
public readonly v1SpeedConfirmNode = new NXLogicConfirmNode(0.3);

Expand Down Expand Up @@ -1663,18 +1669,24 @@ export class FwsCore {
FwsCore.AURAL_SC_INHIBIT_TIME,
);

this.acESSBusPowered.sub((v) => {
if (v) {
this.startupTimer.schedule(() => {
this.startupCompleted.set(true);
console.log('PseudoFWC startup completed.');
}, FwsCore.FWC_STARTUP_TIME);
} else {
this.startupTimer.clear();
this.startupCompleted.set(false);
console.log('PseudoFWC shut down.');
}
});
if (this.fwsNumber === 1) {
this.dcESSBusPowered.sub((v) => this.handlePowerChange(v));
} else {
this.dc2BusPowered.sub((v) => this.handlePowerChange(v));
}
}

private handlePowerChange(powered: boolean) {
if (powered) {
this.startupTimer.schedule(() => {
this.startupCompleted.set(true);
console.log('PseudoFWC startup completed.');
}, FwsCore.FWC_STARTUP_TIME);
} else {
this.startupTimer.clear();
this.startupCompleted.set(false);
console.log('PseudoFWC shut down.');
}
}

private registerKeyEvents() {
Expand Down Expand Up @@ -1846,6 +1858,7 @@ export class FwsCore {
// Inputs update
this.flightPhaseEndedPulseNode.write(false, deltaTime);
this.fwcFlightPhase.set(SimVar.GetSimVarValue('L:A32NX_FWC_FLIGHT_PHASE', 'Enum'));

const phase3 = this.fwcFlightPhase.get() === 3;
const phase6 = this.fwcFlightPhase.get() === 6;
this.flightPhase3PulseNode.write(phase3, deltaTime);
Expand All @@ -1865,6 +1878,15 @@ export class FwsCore {
this.phase815MinConfNode.write(this.fwcFlightPhase.get() === 8, deltaTime);
this.phase112.set(flightPhase112);

this.phase12ShutdownMemoryNode.write(this.fwcFlightPhase.get() == 12, !this.phase112.get());

this.shutDownFor50MinutesCheckListReset.set(
this.shutDownFor50MinutesClResetConfNode.write(
!this.manualCheckListReset.get() && this.phase12ShutdownMemoryNode.read(),
deltaTime,
),
);

// TO CONFIG button
this.toConfigTestRaw = SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool') > 0;
this.toConfigPulseNode.write(this.toConfigTestRaw, _deltaTime);
Expand Down Expand Up @@ -1913,13 +1935,13 @@ export class FwsCore {
);

/* ELECTRICAL acquisition */
this.dcESSBusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_DC_ESS_BUS_IS_POWERED', 'bool'));
this.dc2BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_DC_2_BUS_IS_POWERED', 'bool'));
this.ac1BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_1_BUS_IS_POWERED', 'bool'));
this.ac2BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_2_BUS_IS_POWERED', 'bool'));
this.ac3BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_3_BUS_IS_POWERED', 'bool'));
this.ac4BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_4_BUS_IS_POWERED', 'bool'));
this.acESSBusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_ESS_BUS_IS_POWERED', 'bool'));
this.dcESSBusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_DC_ESS_BUS_IS_POWERED', 'bool') > 0);
this.dc2BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_DC_2_BUS_IS_POWERED', 'bool') > 0);
this.ac1BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_1_BUS_IS_POWERED', 'bool') > 0);
this.ac2BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_2_BUS_IS_POWERED', 'bool') > 0);
this.ac3BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_3_BUS_IS_POWERED', 'bool') > 0);
this.ac4BusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_4_BUS_IS_POWERED', 'bool') > 0);
this.acESSBusPowered.set(SimVar.GetSimVarValue('L:A32NX_ELEC_AC_ESS_BUS_IS_POWERED', 'bool') > 0);

/* ENGINE AND THROTTLE acquisition */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,11 @@ export class FwsMemos {
},
'335000003': {
// NO MOBILE
flightPhaseInhib: [2, 9, 10],
flightPhaseInhib: [],
simVarIsActive: this.fws.noMobileSwitchPosition.map((pos) => pos === 0),
whichCodeToReturn: () => [0],
codesToReturn: ['335000003'],
memoInhibit: () => this.fws.toMemo.get() === 1 || this.fws.ldgMemo.get() === 1,
memoInhibit: () => false,
failure: 0,
sysPage: SdPages.None,
side: 'RIGHT',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// Copyright (c) 2024 FlyByWire Simulations
// SPDX-License-Identifier: GPL-3.0

import { MapSubject, SimVarValueType, Subject, SubscribableMapEventType } from '@microsoft/msfs-sdk';
import {
MappedSubject,
MapSubject,
SimVarValueType,
Subject,
SubscribableMapEventType,
SubscribableMapFunctions,
} from '@microsoft/msfs-sdk';
import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher';
import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore';
import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures';
Expand Down Expand Up @@ -58,6 +65,34 @@ export class FwsNormalChecklists {
this.selectedLine.sub((line) => this.pub.pub('fws_active_line', line + 1, true), true); // Start at second line, headline not selectable
this.showFromLine.sub((line) => this.pub.pub('fws_show_from_line', line, true), true);

this.fws.startupCompleted.sub((v) => {
if (v) {
this.reset(null);
}
});

this.fws.shutDownFor50MinutesCheckListReset.sub((v) => {
if (v) {
this.reset(null);
}
});

this.fws.fwcFlightPhase.sub((phase) => {
if (phase !== 1) {
this.fws.manualCheckListReset.set(false);
}
});

MappedSubject.create(SubscribableMapFunctions.or(), this.fws.eng1Or2TakeoffPower, this.fws.eng3Or4TakeoffPower).sub(
(v) => {
if (v) {
this.reset(
this.getNormalProceduresKeysSorted().findIndex((i) => i === 1000006), // reset starting at departure change,
);
}
},
);

// Populate checklistState
const keys = this.getNormalProceduresKeysSorted();
keys.forEach((k) => {
Expand Down Expand Up @@ -189,23 +224,7 @@ export class FwsNormalChecklists {

// Reset all following checklists
const fromId = this.getNormalProceduresKeysSorted().findIndex((v) => v === this.checklistId.get());
const ids = this.getNormalProceduresKeysSorted();

if (fromId !== -1) {
for (let id = fromId + 1; id < ids.length; id++) {
const idFollowing = ids[id];
const clFollowing = this.checklistState.getValue(idFollowing);
const procFollowing = EcamNormalProcedures[idFollowing];
const clStateFollowing: ChecklistState = {
id: idFollowing,
checklistCompleted: procFollowing.deferred ? true : false,
itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) =>
procFollowing.items[index].sensed ? val : false,
),
};
this.checklistState.setValue(idFollowing, clStateFollowing);
}
}
this.reset(fromId);
this.checklistState.setValue(this.checklistId.get(), clState);
this.selectFirst();
}
Expand Down Expand Up @@ -280,6 +299,26 @@ export class FwsNormalChecklists {
}
}

private reset(fromId: number | null) {
if (fromId !== -1) {
const ids = this.getNormalProceduresKeysSorted();
this.fws.manualCheckListReset.set(fromId !== null);
for (let id = fromId === null ? 0 : fromId + 1; id < ids.length; id++) {
const idFollowing = ids[id];
const clFollowing = this.checklistState.getValue(idFollowing);
const procFollowing = EcamNormalProcedures[idFollowing];
const clStateFollowing: ChecklistState = {
id: idFollowing,
checklistCompleted: procFollowing.deferred ? true : false,
itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) =>
procFollowing.items[index].sensed ? val : false,
),
};
this.checklistState.setValue(idFollowing, clStateFollowing);
}
}
}

public sensedItems: FwsNormalChecklistsDict = {
1000001: {
whichItemsChecked: () => [null, null, !!this.fws.seatBelt.get(), null],
Expand Down