Skip to content

Commit

Permalink
feat(nd): true ref for navaids
Browse files Browse the repository at this point in the history
  • Loading branch information
tracernz committed Dec 7, 2022
1 parent 73cbc1b commit 1d14c8b
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 54 deletions.
64 changes: 43 additions & 21 deletions src/instruments/src/ND/elements/RadioNavInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useSimVar } from '@instruments/common/simVars';
import { TuningMode } from '@fmgc/radionav';
import { EfisSide } from '@shared/NavigationDisplay';
import { EfisSide, Mode } from '@shared/NavigationDisplay';

export enum NavAidMode {
Off = 0,
ADF,
VOR,
}

// TODO true ref

export type RadioNavInfoProps = { index: 1 | 2, side: EfisSide }
export type RadioNavInfoProps = {
index: 1 | 2,
side: EfisSide,
trueRef: boolean,
mode: Mode,
}

const TuningModeIndicator: React.FC<{ index: 1 | 2, frequency: number }> = ({ index, frequency }) => {
const [tuningMode] = useSimVar(`L:A32NX_FMGC_RADIONAV_${index}_TUNING_MODE`, 'enum');
Expand All @@ -23,12 +26,28 @@ const TuningModeIndicator: React.FC<{ index: 1 | 2, frequency: number }> = ({ in
);
};

const VorInfo: React.FC<{index: 1 | 2}> = ({ index }) => {
const VorInfo: React.FC<{index: 1 | 2, trueRef: boolean, mode: Mode }> = ({ index, trueRef, mode }) => {
const [vorIdent] = useSimVar(`NAV IDENT:${index}`, 'string');
const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz');
const [vorHasDme] = useSimVar(`NAV HAS DME:${index}`, 'bool');
const [dmeDistance] = useSimVar(`NAV DME:${index}`, 'nautical miles');
const [vorAvailable] = useSimVar(`NAV HAS NAV:${index}`, 'boolean');
const [stationDeclination] = useSimVar(`NAV MAGVAR:${index}`, 'degrees');
const [stationLocation] = useSimVar(`NAV VOR LATLONALT:${index}`, 'latlonalt');
const [stationRefTrue, setStationRefTrue] = useState(false);
const [corrected, setCorrected] = useState(false);
const [magWarning, setMagWarning] = useState(false);
const [trueWarning, setTrueWarning] = useState(false);

useEffect(() => {
setStationRefTrue(stationLocation.lat > 75 && stationDeclination < Number.EPSILON);
}, [stationDeclination, stationLocation.lat]);

useEffect(() => {
setCorrected(vorAvailable && !!(trueRef) !== stationRefTrue && mode !== Mode.ROSE_VOR && mode !== Mode.ROSE_ILS);
setMagWarning(vorAvailable && !!(trueRef) && !stationRefTrue && (mode === Mode.ROSE_VOR || mode === Mode.ROSE_ILS));
setTrueWarning(vorAvailable && !(trueRef) && stationRefTrue && (mode === Mode.ROSE_VOR || mode === Mode.ROSE_ILS));
}, [trueRef, stationRefTrue, mode, vorAvailable]);

const x = index === 1 ? 37 : 668;

Expand Down Expand Up @@ -60,21 +79,24 @@ const VorInfo: React.FC<{index: 1 | 2}> = ({ index }) => {

return (
<g className="GtLayer">
{(vorAvailable && (
<path
d={path}
strokeWidth={2}
className="White"
strokeLinejoin="round"
strokeLinecap="round"
/>
))}
<path
d={path}
strokeWidth={2}
className={vorAvailable && !!(trueRef) !== stationRefTrue && (mode === Mode.ARC || mode === Mode.ROSE_NAV) ? 'Magenta' : 'White'}
strokeLinejoin="round"
strokeLinecap="round"
/>
<text x={x} y={692} fontSize={24} className="White">
VOR
{index}
</text>
{(vorAvailable || vorHasDme) && vorFrequency > 1 && (
<text x={x} y={722} fontSize={24} className="White">{vorIdent}</text>
<>
<text x={x} y={722} fontSize={24} className="White">{vorIdent}</text>
<text x={index === 2 ? x - 52 : x + 69} y={692} fontSize={18} className="Magenta" visibility={corrected ? 'inherit' : 'hidden'}>CORR</text>
<text x={index === 2 ? x - 52 : x + 81} y={692} fontSize={18} className="Amber" visibility={magWarning ? 'inherit' : 'hidden'}>MAG</text>
<text x={index === 2 ? x - 52 : x + 69} y={692} fontSize={18} className="Amber" visibility={trueWarning ? 'inherit' : 'hidden'}>TRUE</text>
</>
)}
{!(vorAvailable || vorHasDme) && vorFrequency > 1 && (
<text x={index === 2 ? x - 26 : x} y={722} fontSize={24} className="White">{freqText}</text>
Expand Down Expand Up @@ -122,13 +144,13 @@ const AdfInfo: React.FC<{index: 1 | 2}> = ({ index }) => {
);
};

export const RadioNavInfo: React.FC<RadioNavInfoProps> = ({ index, side }) => {
const [mode] = useSimVar(`L:A32NX_EFIS_${side}_NAVAID_${index}_MODE`, 'enum');
export const RadioNavInfo: React.FC<RadioNavInfoProps> = ({ index, side, trueRef, mode }) => {
const [navaidMode] = useSimVar(`L:A32NX_EFIS_${side}_NAVAID_${index}_MODE`, 'enum');

if (mode === NavAidMode.VOR) {
return <VorInfo index={index} />;
if (navaidMode === NavAidMode.VOR) {
return <VorInfo index={index} trueRef={trueRef} mode={mode} />;
}
if (mode === NavAidMode.ADF) {
if (navaidMode === NavAidMode.ADF) {
return <AdfInfo index={index} />;
}
return <></>;
Expand Down
30 changes: 19 additions & 11 deletions src/instruments/src/ND/elements/RadioNeedles.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useSimVar } from '@instruments/common/simVars';
import { Mode, EfisSide } from '@shared/NavigationDisplay';
import { NavAidMode } from './RadioNavInfo';

type RadioNavPointerProps = { index: 1 | 2, side: EfisSide, displayMode: Mode, centreHeight: number };
type RadioNavPointerProps = { index: 1 | 2, side: EfisSide, displayMode: Mode, centreHeight: number, trueRef: boolean };

const AdfNeedle: React.FC<Omit<RadioNavPointerProps, 'side'>> = ({ index, displayMode, centreHeight }) => {
const [relativeBearing] = useSimVar(`ADF RADIAL:${index}`, 'degrees');
Expand Down Expand Up @@ -36,20 +36,28 @@ const AdfNeedle: React.FC<Omit<RadioNavPointerProps, 'side'>> = ({ index, displa
<path
d={paths[index - 1]}
strokeWidth={3.7}
className="shadow rounded"
className="rounded shadow"
/>
<path
d={paths[index - 1]}
strokeWidth={3.2}
className="Green rounded"
className="rounded Green"
/>
</g>
);
};

const VorNeedle: React.FC<Omit<RadioNavPointerProps, 'side'>> = ({ index, displayMode, centreHeight }) => {
const VorNeedle: React.FC<Omit<RadioNavPointerProps, 'side'>> = ({ index, displayMode, centreHeight, trueRef }) => {
const [relativeBearing] = useSimVar(`NAV RELATIVE BEARING TO STATION:${index}`, 'degrees');
const [available] = useSimVar(`NAV HAS NAV:${index}`, 'number');
const [isLoc] = useSimVar(`NAV HAS LOCALIZER:${index}`, 'number');
const [stationDeclination] = useSimVar(`NAV MAGVAR:${index}`, 'degrees');
const [stationLocation] = useSimVar(`NAV VOR LATLONALT:${index}`, 'latlonalt');
const [stationRefTrue, setStationRefTrue] = useState(false);

useEffect(() => {
setStationRefTrue(stationLocation.lat > 75 && stationDeclination < Number.EPSILON);
}, [stationDeclination, stationLocation.lat]);

let paths: Array<string>;

Expand All @@ -73,30 +81,30 @@ const VorNeedle: React.FC<Omit<RadioNavPointerProps, 'side'>> = ({ index, displa
return null;
}

return available && (
return available && !isLoc && (
<g transform={`rotate(${relativeBearing} 384 ${centreHeight})`}>
<path
d={paths[index - 1]}
strokeWidth={3.7}
className="shadow rounded"
className="rounded shadow"
/>
<path
d={paths[index - 1]}
strokeWidth={3.2}
className="White rounded"
className={`rounded ${!!(trueRef) !== stationRefTrue ? 'Magenta' : 'White'}`}
/>
</g>
);
};

export const RadioNeedle: React.FC<RadioNavPointerProps> = ({ index, side, displayMode, centreHeight }) => {
export const RadioNeedle: React.FC<RadioNavPointerProps> = ({ index, side, displayMode, centreHeight, trueRef }) => {
const [mode] = useSimVar(`L:A32NX_EFIS_${side}_NAVAID_${index}_MODE`, 'enum');

switch (mode) {
case NavAidMode.ADF:
return <AdfNeedle index={index} displayMode={displayMode} centreHeight={centreHeight} />;
return <AdfNeedle index={index} displayMode={displayMode} centreHeight={centreHeight} trueRef={trueRef} />;
case NavAidMode.VOR:
return <VorNeedle index={index} displayMode={displayMode} centreHeight={centreHeight} />;
return <VorNeedle index={index} displayMode={displayMode} centreHeight={centreHeight} trueRef={trueRef} />;
case NavAidMode.Off:
default:
return null;
Expand Down
14 changes: 12 additions & 2 deletions src/instruments/src/ND/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ const NavigationDisplay: React.FC = () => {
}
}, []));

const irMaint = useArinc429Var('L:A32NX_ADIRS_IR_1_MAINT_WORD');
const [trueRefPb] = useSimVar('L:A32NX_PUSH_TRUE_REF', 'bool');
const [trueRef, setTrueRef] = useState(false);

useEffect(() => {
setTrueRef((irMaint.getBitValueOr(15, false) || trueRefPb) && !irMaint.getBitValueOr(2, false));
}, [irMaint.value, trueRefPb]);

return (
<DisplayUnit
electricitySimvar={displayIndex === 1 ? 'L:A32NX_ELEC_AC_ESS_BUS_IS_POWERED' : 'L:A32NX_ELEC_AC_2_BUS_IS_POWERED'}
Expand Down Expand Up @@ -131,6 +139,7 @@ const NavigationDisplay: React.FC = () => {
side={side}
ppos={ppos}
mapHidden={modeChangeShown || rangeChangeShown}
trueRef={trueRef}
/>
)}
{(modeIndex === Mode.ROSE_ILS || modeIndex === Mode.ROSE_VOR || modeIndex === Mode.ROSE_NAV)
Expand All @@ -143,6 +152,7 @@ const NavigationDisplay: React.FC = () => {
ppos={ppos}
mode={modeIndex}
mapHidden={modeChangeShown || rangeChangeShown}
trueRef={trueRef}
/>
)}

Expand All @@ -151,8 +161,8 @@ const NavigationDisplay: React.FC = () => {
<NavigationDisplayMessages adirsAlign={adirsAlign} mode={modeIndex} modeChangeShown={modeChangeShown} rangeChangeShown={rangeChangeShown} />
{(adirsAlign && modeIndex !== Mode.PLAN) && (
<>
<RadioNavInfo index={1} side={side} />
<RadioNavInfo index={2} side={side} />
<RadioNavInfo index={1} side={side} trueRef={trueRef} mode={modeIndex} />
<RadioNavInfo index={2} side={side} trueRef={trueRef} mode={modeIndex} />
</>
)}
<TcasWxrMessages modeIndex={modeIndex} />
Expand Down
14 changes: 4 additions & 10 deletions src/instruments/src/ND/pages/ArcMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ export interface ArcModeProps {
side: EfisSide,
ppos: LatLongData,
mapHidden: boolean,
trueRef: boolean,
}

export const ArcMode: React.FC<ArcModeProps> = ({ symbols, adirsAlign, rangeSetting, side, ppos, mapHidden }) => {
export const ArcMode: React.FC<ArcModeProps> = ({ symbols, adirsAlign, rangeSetting, side, ppos, mapHidden, trueRef }) => {
// TODO arinc var selector
const magHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_HEADING');
const magTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRACK');
Expand All @@ -36,9 +37,6 @@ export const ArcMode: React.FC<ArcModeProps> = ({ symbols, adirsAlign, rangeSett
const [lsDisplayed] = useSimVar(`L:BTN_LS_${side === 'L' ? 1 : 2}_FILTER_ACTIVE`, 'bool'); // TODO rename simvar
const [fmaLatMode] = useSimVar('L:A32NX_FMA_LATERAL_MODE', 'enum', 200);
const [armedLateralBitmask] = useSimVar('L:A32NX_FMA_LATERAL_ARMED', 'enum', 200);
const irMaint = useArinc429Var('L:A32NX_ADIRS_IR_1_MAINT_WORD');
const [trueRefPb] = useSimVar('L:A32NX_PUSH_TRUE_REF', 'bool');
const [trueRef, setTrueRef] = useState(false);

const heading = Number(MathUtils.fastToFixed((trueRef ? trueHeading.value : magHeading.value), 2));
const track = Number(MathUtils.fastToFixed((trueRef ? trueTrack.value : magTrack.value), 2));
Expand All @@ -54,10 +52,6 @@ export const ArcMode: React.FC<ArcModeProps> = ({ symbols, adirsAlign, rangeSett
mapParams.compute(ppos, rangeSetting, 492, trueHeading.value);
}, [ppos.lat, ppos.long, trueHeading.value, rangeSetting].map((n) => MathUtils.fastToFixed(n, 6)));

useEffect(() => {
setTrueRef((irMaint.getBitValueOr(15, false) || trueRefPb) && !irMaint.getBitValueOr(2, false));
}, [irMaint.value, trueRefPb]);

if (adirsAlign) {
return (
<>
Expand Down Expand Up @@ -87,8 +81,8 @@ export const ArcMode: React.FC<ArcModeProps> = ({ symbols, adirsAlign, rangeSett
<TrackLine x={384} y={620} heading={heading} track={track} />
)}
</g>
<RadioNeedle index={1} side={side} displayMode={Mode.ARC} centreHeight={620} />
<RadioNeedle index={2} side={side} displayMode={Mode.ARC} centreHeight={620} />
<RadioNeedle index={1} side={side} displayMode={Mode.ARC} centreHeight={620} trueRef={trueRef} />
<RadioNeedle index={2} side={side} displayMode={Mode.ARC} centreHeight={620} trueRef={trueRef} />
</g>

<ToWaypointIndicator side={side} trueRef={trueRef} />
Expand Down
14 changes: 4 additions & 10 deletions src/instruments/src/ND/pages/RoseMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export interface RoseModeProps {
side: EfisSide,
ppos: LatLongData,
mapHidden: boolean,
trueRef: boolean,
}

export const RoseMode: FC<RoseModeProps> = ({ symbols, adirsAlign, rangeSetting, mode, side, ppos, mapHidden }) => {
export const RoseMode: FC<RoseModeProps> = ({ symbols, adirsAlign, rangeSetting, mode, side, ppos, mapHidden, trueRef }) => {
const magHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_HEADING');
const magTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRACK');
const trueHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_HEADING');
Expand All @@ -37,9 +38,6 @@ export const RoseMode: FC<RoseModeProps> = ({ symbols, adirsAlign, rangeSetting,
const [lsDisplayed] = useSimVar(`L:BTN_LS_${side === 'L' ? 1 : 2}_FILTER_ACTIVE`, 'bool'); // TODO rename simvar
const [fmaLatMode] = useSimVar('L:A32NX_FMA_LATERAL_MODE', 'enum', 200);
const [armedLateralBitmask] = useSimVar('L:A32NX_FMA_LATERAL_ARMED', 'enum', 200);
const irMaint = useArinc429Var('L:A32NX_ADIRS_IR_1_MAINT_WORD');
const [trueRefPb] = useSimVar('L:A32NX_PUSH_TRUE_REF', 'bool');
const [trueRef, setTrueRef] = useState(false);

const heading = Number(MathUtils.fastToFixed((trueRef ? trueHeading.value : magHeading.value), 2));
const track = Number(MathUtils.fastToFixed((trueRef ? trueTrack.value : magTrack.value), 2));
Expand All @@ -55,10 +53,6 @@ export const RoseMode: FC<RoseModeProps> = ({ symbols, adirsAlign, rangeSetting,
mapParams.compute(ppos, rangeSetting / 2, 250, trueHeading.value);
}, [ppos.lat, ppos.long, trueHeading.value, rangeSetting].map((n) => MathUtils.fastToFixed(n, 6)));

useEffect(() => {
setTrueRef((irMaint.getBitValueOr(15, false) || trueRefPb) && !irMaint.getBitValueOr(2, false));
}, [irMaint.value, trueRefPb]);

if (adirsAlign) {
return (
<>
Expand Down Expand Up @@ -88,8 +82,8 @@ export const RoseMode: FC<RoseModeProps> = ({ symbols, adirsAlign, rangeSetting,
)}
</g>
)}
<RadioNeedle index={1} side={side} displayMode={mode} centreHeight={384} />
<RadioNeedle index={2} side={side} displayMode={mode} centreHeight={384} />
<RadioNeedle index={1} side={side} displayMode={mode} centreHeight={384} trueRef={trueRef} />
<RadioNeedle index={2} side={side} displayMode={mode} centreHeight={384} trueRef={trueRef} />
</g>

{ mode === Mode.ROSE_VOR && <VorCaptureOverlay heading={heading} side={side} /> }
Expand Down

0 comments on commit 1d14c8b

Please sign in to comment.