11import {
2- AdcEvents , AltitudeSelectEvents , AltitudeSelectManager , AltitudeSelectManagerOptions , APAltitudeModes , APEvents , APLateralModes ,
3- APModePressEvent , APStateManager , APVerticalModes , Autopilot , ConsumerSubject , ConsumerValue , DirectorState ,
4- EventBus , FlightPlanner , MappedSubject , MetricAltitudeSettingsManager , MinimumsMode , NavSourceType , ObjectSubject ,
5- PlaneDirector ,
6- RadioUtils , SetSubject , SimVarValueType , Subject , UnitType , VNavAltCaptureType , VNavState
2+ AdcEvents , AltitudeSelectEvents , AltitudeSelectManager , AltitudeSelectManagerOptions , APAltitudeModes , APEvents ,
3+ APLateralModes , APModePressEvent , APStateManager , APVerticalModes , Autopilot , ConsumerSubject , ConsumerValue ,
4+ DirectorState , EventBus , FlightPlanner , MappedSubject , MetricAltitudeSettingsManager , MinimumsMode , NavSourceType ,
5+ ObjectSubject , PlaneDirector , RadioUtils , SetSubject , SimVarValueType , Subject , UnitType , VNavAltCaptureType ,
6+ VNavState
77} from '@microsoft/msfs-sdk' ;
88
99import { MinimumsDataProvider } from '../minimums/MinimumsDataProvider' ;
1010import { GarminAPVars } from './data/GarminAPEvents' ;
1111import { FmaData , FmaDataEvents , FmaVNavState } from './FmaData' ;
1212import { GarminAPConfigInterface } from './GarminAPConfigInterface' ;
13+ import { GarminAPUtils } from './GarminAPUtils' ;
1314import { GarminVNavManager2 } from './vnav/GarminVNavManager2' ;
1415
1516/**
@@ -77,18 +78,7 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
7778
7879 protected readonly isAltSelectInitialized = ConsumerValue . create ( null , true ) ;
7980
80- protected readonly fmaData = ObjectSubject . create < FmaData > ( {
81- verticalActive : APVerticalModes . NONE ,
82- verticalArmed : APVerticalModes . NONE ,
83- verticalApproachArmed : APVerticalModes . NONE ,
84- verticalAltitudeArmed : APAltitudeModes . NONE ,
85- altitudeCaptureArmed : false ,
86- altitudeCaptureValue : - 1 ,
87- lateralActive : APLateralModes . NONE ,
88- lateralArmed : APLateralModes . NONE ,
89- lateralModeFailed : false ,
90- vnavState : FmaVNavState . OFF
91- } ) ;
81+ protected readonly fmaData = ObjectSubject . create < FmaData > ( GarminAPUtils . createEmptyFmaData ( ) ) ;
9282
9383 protected readonly fmaDataPublisher = this . bus . getPublisher < FmaDataEvents > ( ) ;
9484 protected needPublishFmaData = false ;
@@ -103,6 +93,13 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
10393
10494 protected isApproachModeCommandedOn = false ;
10595
96+ protected lateralModeReversionFromMode : number | null = null ;
97+ protected lateralModeReversionToMode : number | null = null ;
98+
99+ protected verticalModeReversionFromMode : number | null = null ;
100+ protected verticalModeReversionFromAltitudeMode : APAltitudeModes | null = null ;
101+ protected verticalModeReversionToMode : number | null = null ;
102+
106103 /**
107104 * Creates a new instance of GarminAutopilot.
108105 * @param bus The event bus.
@@ -287,6 +284,7 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
287284 protected onAfterUpdate ( ) : void {
288285 this . updateApproachModeState ( ) ;
289286 this . updateNavModeState ( ) ;
287+ this . updateModeReversionState ( ) ;
290288 this . updateFma ( ) ;
291289 }
292290
@@ -339,6 +337,41 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
339337 }
340338 }
341339
340+ /**
341+ * Updates this autopilot's mode reversion state.
342+ */
343+ protected updateModeReversionState ( ) : void {
344+ if ( ! this . stateManager . apMasterOn . get ( ) && ! this . stateManager . isAnyFlightDirectorOn . get ( ) ) {
345+ // If flight director is not on, then reset all mode reversions.
346+
347+ this . lateralModeReversionFromMode = null ;
348+ this . lateralModeReversionToMode = null ;
349+ this . verticalModeReversionFromMode = null ;
350+ this . verticalModeReversionFromAltitudeMode = null ;
351+ this . verticalModeReversionToMode = null ;
352+ } else {
353+ // If flight director is on, then reset mode reversions if the corresponding active mode is not either NONE
354+ // or the mode to which the original mode reverted.
355+
356+ if ( this . lateralModeReversionToMode !== null ) {
357+ const lateralActiveMode = this . apValues . lateralActive . get ( ) ;
358+ if ( lateralActiveMode !== this . lateralModeReversionToMode && lateralActiveMode !== APLateralModes . NONE ) {
359+ this . lateralModeReversionFromMode = null ;
360+ this . lateralModeReversionToMode = null ;
361+ }
362+ }
363+
364+ if ( this . verticalModeReversionToMode !== null ) {
365+ const verticalActiveMode = this . apValues . verticalActive . get ( ) ;
366+ if ( verticalActiveMode !== this . verticalModeReversionToMode && verticalActiveMode !== APVerticalModes . NONE ) {
367+ this . verticalModeReversionFromMode = null ;
368+ this . verticalModeReversionFromAltitudeMode = null ;
369+ this . verticalModeReversionToMode = null ;
370+ }
371+ }
372+ }
373+ }
374+
342375 /**
343376 * Publishes data for the FMA.
344377 */
@@ -364,6 +397,9 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
364397 fmaData . set ( 'lateralActive' , this . apValues . lateralActive . get ( ) ) ;
365398 fmaData . set ( 'lateralArmed' , this . apValues . lateralArmed . get ( ) ) ;
366399 fmaData . set ( 'lateralModeFailed' , this . lateralModeFailed ) ;
400+ fmaData . set ( 'lateralReversionFromMode' , this . lateralModeReversionFromMode ) ;
401+ fmaData . set ( 'verticalReversionFromMode' , this . verticalModeReversionFromMode ) ;
402+ fmaData . set ( 'verticalAltitudeReversionFromMode' , this . verticalModeReversionFromAltitudeMode ) ;
367403 fmaData . set ( 'vnavState' , fmaVNavState ) ;
368404
369405 if ( this . needPublishFmaData ) {
@@ -596,4 +632,66 @@ export class GarminAutopilot extends Autopilot<GarminAPConfigInterface> {
596632
597633 super . checkModes ( ) ;
598634 }
635+
636+ /** @inheritDoc */
637+ protected handleLateralActiveModeReversion ( mode : number ) : void {
638+ // For backward compatibility.
639+ if ( mode !== APLateralModes . NONE ) {
640+ this . lateralModeFailed = true ;
641+ }
642+
643+ // Immediately set the active lateral mode to NONE and attempt to activate the NONE director. We do this in order
644+ // to guarantee that the reverted mode is not left as the active lateral mode.
645+ this . apValues . lateralActive . set ( APLateralModes . NONE ) ;
646+ this . lateralModes . get ( APLateralModes . NONE ) ?. activate ( ) ;
647+
648+ // Immediately deactivate the armed lateral mode, if there is one. We do this to guarantee that during a
649+ // reversion, the armed mode ends up as either the default lateral mode (see below) or NONE.
650+ const lateralArmedMode = this . apValues . lateralArmed . get ( ) ;
651+ if ( lateralArmedMode !== APLateralModes . NONE ) {
652+ this . lateralModes . get ( lateralArmedMode ) ?. deactivate ( ) ;
653+ this . apValues . lateralArmed . set ( APLateralModes . NONE ) ;
654+ }
655+
656+ // Attempt to arm the default lateral mode. If the default lateral mode is NONE, then we can skip arming because
657+ // we've already activated the NONE director above.
658+ const modeToArm = this . getDefaultLateralMode ( ) ;
659+ if ( modeToArm !== APLateralModes . NONE ) {
660+ this . lateralModes . get ( modeToArm ) ?. arm ( ) ;
661+ }
662+
663+ if ( mode !== APLateralModes . NONE ) {
664+ this . lateralModeReversionFromMode = mode ;
665+ this . lateralModeReversionToMode = modeToArm ;
666+ }
667+ }
668+
669+ /** @inheritDoc */
670+ protected handleVerticalActiveModeReversion ( mode : number ) : void {
671+ // Immediately set the active vertical mode to NONE and attempt to activate the NONE director. We do this in
672+ // order to guarantee that the reverted mode is not left as the active vertical mode.
673+ this . apValues . verticalActive . set ( APVerticalModes . NONE ) ;
674+ this . verticalModes . get ( APVerticalModes . NONE ) ?. activate ( ) ;
675+
676+ // Immediately deactivate the armed vertical mode, if there is one. We do this to guarantee that during a
677+ // reversion, the armed mode ends up as either the default vertical mode (see below) or NONE.
678+ const verticalArmedMode = this . apValues . verticalArmed . get ( ) ;
679+ if ( verticalArmedMode !== APLateralModes . NONE ) {
680+ this . verticalModes . get ( verticalArmedMode ) ?. deactivate ( ) ;
681+ this . apValues . verticalArmed . set ( APLateralModes . NONE ) ;
682+ }
683+
684+ // Attempt to arm the default vertical mode. If the default vertical mode is NONE, then we can skip arming
685+ // because we've already activated the NONE director above.
686+ const modeToArm = this . getDefaultVerticalMode ( ) ;
687+ if ( modeToArm !== APVerticalModes . NONE ) {
688+ this . verticalModes . get ( modeToArm ) ?. arm ( ) ;
689+ }
690+
691+ if ( mode !== APVerticalModes . NONE ) {
692+ this . verticalModeReversionFromMode = mode ;
693+ this . verticalModeReversionFromAltitudeMode = this . verticalAltitudeArmed ;
694+ this . verticalModeReversionToMode = modeToArm ;
695+ }
696+ }
599697}
0 commit comments