G1000: manual-accurate radios, baro units, declutter, minimums, OBS, audio panel

Aligned to the official X-Plane 1000 manual:
- NAV radio: active RIGHT / standby LEFT (boxed) per S.12 (COM already correct)
- ALT UNIT softkey (IN / HPA) in the PFD submenu, baro readout converts (S.20)
- DCLTR cycles 3 levels (land / +NDB / flight-plan only) with DCLTR-n label (S.56)
- TOPO and TERRAIN are now independent toggles (relief vs awareness overlay) (S.57)
- Barometric MINIMUMS: BARO MIN bug + readout on the altimeter, amber "MINIMUMS"
  annunciation at/below the decision altitude; set via TMR/REF (lifted to App)
- OBS mode: HSI course follows the CRS knob (magenta "OBS"), sequencing suspended
- New Audio Panel tab (COM mic/receive, MKR/DME/ADF, intercom, Display Backup) (S.91)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 05:55:56 +02:00
parent 38b048ad41
commit 033a9d406a
10 changed files with 290 additions and 97 deletions
+17 -5
View File
@@ -10,6 +10,7 @@ import Bezel from './components/Bezel.jsx';
import DirectTo from './components/DirectTo.jsx';
import Proc from './components/Proc.jsx';
import FplPage from './components/FplPage.jsx';
import AudioPanel from './components/AudioPanel.jsx';
// Compact line icons for the nav rail (stroke = currentColor).
const ICONS = {
@@ -19,6 +20,7 @@ const ICONS = {
fms: 'M4 6h14M4 11h14M4 16h9',
ap: 'M11 4a7 7 0 100 14 7 7 0 000-14zM11 4v3M11 15v3M4 11h3M15 11h3',
vfr: 'M11 4a7 7 0 100 14 7 7 0 000-14zM11 11l4.5-3',
audio: 'M11 4a6 6 0 00-6 6v5M17 15v-5a6 6 0 00-6-6M4 14h2.5v4.5H4zM15.5 14H18v4.5h-2.5z',
};
function Icon({ name }) {
return (
@@ -37,6 +39,7 @@ const TABS = [
{ id: 'fms', label: 'FMS' },
{ id: 'vfr', label: 'VFR' },
{ id: 'ap', label: 'Autopilot' },
{ id: 'audio', label: 'Audio' },
];
export default function App() {
@@ -65,8 +68,14 @@ export default function App() {
const toggleWin = (id) => setWin((w) => (w === id ? null : id));
const nrst = win === 'nrst', tmr = win === 'tmr', dme = win === 'dme', alerts = win === 'alerts';
const fpl = win === 'fpl', dto = win === 'dto', proc = win === 'proc';
// MFD map mode (base layer), switched via the Map-Opt softkeys.
// MFD map mode (base layer + overlays), switched via the Map-Opt softkeys.
const [mapMode, setMapMode] = useState({ base: 'topo' });
// Altimeter barometric units (false = inHg, true = hectopascal) — PFD ALT UNIT softkey.
const [baroHpa, setBaroHpa] = useState(false);
// Barometric minimums (set in TMR/REF) — shown on the PFD altimeter as BARO MIN.
const [minimums, setMinimums] = useState({ on: false, ft: 500 });
// OBS (omni-bearing select) mode — suspends GPS sequencing, course set by CRS knob.
const [obs, setObs] = useState(false);
// MFD page group (MAP / FPL / NRST) — selected by the FMS knob, like the real G1000.
const MFD_PAGES = ['map', 'fpl', 'nrst'];
const [mfdPage, setMfdPage] = useState('map');
@@ -129,15 +138,17 @@ export default function App() {
inset={inset} onSetInset={setInset} insetMode={insetMode} onInsetMode={setInsetMode}
nrst={nrst} onToggleNrst={() => toggleWin('nrst')} onDirect={() => toggleWin('dto')}
tmr={tmr} onToggleTmr={() => toggleWin('tmr')} dme={dme} onToggleDme={() => toggleWin('dme')}
alerts={alerts} onToggleAlerts={() => toggleWin('alerts')} onProc={() => toggleWin('proc')} onFpl={() => toggleWin('fpl')}>
<PFD values={xp.values} command={xp.command} svt={svt3d} inset={inset} insetMode={insetMode} nrst={nrst} onCloseNrst={() => setWin(null)}
alerts={alerts} onToggleAlerts={() => toggleWin('alerts')} onProc={() => toggleWin('proc')} onFpl={() => toggleWin('fpl')} onClr={() => setWin(null)}
altHpa={baroHpa} onAltUnit={setBaroHpa} obs={obs} onObs={() => setObs((v) => !v)}>
<PFD values={xp.values} command={xp.command} connected={xp.xpConnected} svt={svt3d} inset={inset} insetMode={insetMode} nrst={nrst} onCloseNrst={() => setWin(null)}
tmr={tmr} onCloseTmr={() => setWin(null)} dme={dme} onCloseDme={() => setWin(null)}
alerts={alerts} onCloseAlerts={() => setWin(null)} flightPlan={xp.flightPlan} fp={xp.fp} />
alerts={alerts} onCloseAlerts={() => setWin(null)} baroHpa={baroHpa} obs={obs}
minimums={minimums} onMinimums={setMinimums} flightPlan={xp.flightPlan} fp={xp.fp} />
{dialogs}
</Bezel>
)}
{tab === 'mfd' && (
<Bezel variant="mfd" xp={xp} knobMode={knobMode} mapMode={mapMode} onMapMode={setMapMode} onDirect={() => toggleWin('dto')} onProc={() => toggleWin('proc')} onFms={cycleMfd} onFpl={() => setMfdPage('fpl')}>
<Bezel variant="mfd" xp={xp} knobMode={knobMode} mapMode={mapMode} onMapMode={setMapMode} onDirect={() => toggleWin('dto')} onProc={() => toggleWin('proc')} onFms={cycleMfd} onFpl={() => setMfdPage('fpl')} onClr={() => setWin(null)}>
<MFD values={xp.values} flightPlan={xp.flightPlan} fp={xp.fp} mapMode={mapMode} page={mfdPage} onCycle={cycleMfd} xp={xp} />
{dialogs}
</Bezel>
@@ -146,6 +157,7 @@ export default function App() {
{tab === 'fms' && <CDU xp={xp} />}
{tab === 'vfr' && <VFR xp={xp} />}
{tab === 'ap' && <AutopilotPanel xp={xp} />}
{tab === 'audio' && <AudioPanel xp={xp} />}
</main>
{settings && (
<div className="dlg-backdrop" onClick={() => setSettings(false)}>