132 lines
4.9 KiB
C
132 lines
4.9 KiB
C
// NAV / COM / ADF radios. Holds the four tuned frequencies plus
|
|
// VOR1/VOR2 OBS courses, looks up the active station for each radio
|
|
// against the unified scenery station database, and exposes the
|
|
// per-frame derived values the panel digits and gauge needles read.
|
|
//
|
|
// Frequency encoding mirrors FS2's chunk5 `DecodeBCDFreqString` and
|
|
// chunk3 `LookupADFStation`: NAV/COM are two BCD pairs giving
|
|
// XXX.X MHz (e.g. 0x1080 == 108.0 MHz, 0x1224 == 122.4 MHz). ADF is
|
|
// `[BCD pair (mid+lo)] [single high digit]`, so 0x0703 == 703 kHz.
|
|
|
|
#ifndef RADIOS_H
|
|
#define RADIOS_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include "aircraft.h"
|
|
#include "sceneryStationsData.h"
|
|
|
|
|
|
typedef enum RadioE {
|
|
RADIO_NAV1 = 0,
|
|
RADIO_NAV2 = 1,
|
|
RADIO_ADF = 2,
|
|
RADIO_COM1 = 3,
|
|
RADIO_COUNT
|
|
} RadioE;
|
|
|
|
|
|
// VOR TO/FROM/OFF flag, indexed into chunk5 msg_vor_flags.
|
|
typedef enum VorFlagE {
|
|
VOR_FLAG_OFF = 0,
|
|
VOR_FLAG_TO = 1,
|
|
VOR_FLAG_FR = 2
|
|
} VorFlagE;
|
|
|
|
|
|
typedef struct RadiosT {
|
|
// BCD-packed tuned frequencies. See the file-level comment for
|
|
// the encoding.
|
|
uint16_t nav1Freq;
|
|
uint16_t nav2Freq;
|
|
uint16_t adfFreq;
|
|
uint16_t com1Freq;
|
|
|
|
// OBS courses for VOR1/VOR2 (byte angles, 256 == full turn).
|
|
// Set by the pilot via the panel; the needle deflects from
|
|
// course-line intercept.
|
|
uint8_t nav1Obs;
|
|
uint8_t nav2Obs;
|
|
|
|
// Active station pointers (NULL = no station found at the
|
|
// current frequency). Refreshed on tune-change and whenever
|
|
// the aircraft moves into a different region's coverage.
|
|
const StationDataT *nav1Station;
|
|
const StationDataT *nav2Station;
|
|
const StationDataT *adfStation;
|
|
const StationDataT *com1Station;
|
|
|
|
// Per-frame derived values, recomputed by `radiosUpdate`.
|
|
// Bearings are byte angles (0 = north, 64 = east). DME is
|
|
// nautical miles, integer (FS2 displayed it as "000"-style).
|
|
// Needle deflections are signed byte deflection from "needle
|
|
// centred", saturating at +/-32 -- matches needleData range.
|
|
uint8_t nav1RelativeBearing;
|
|
uint8_t nav2RelativeBearing;
|
|
uint8_t adfRelativeBearing; // station bearing minus aircraft heading
|
|
uint16_t nav1Dme;
|
|
uint16_t nav2Dme;
|
|
int8_t nav1NeedleDefl;
|
|
int8_t nav2NeedleDefl;
|
|
bool nav1Valid; // active station present + in receivable range
|
|
bool nav2Valid;
|
|
bool adfValid;
|
|
|
|
// VOR1/VOR2 TO/FROM/OFF flag, mirroring chunk5 msg_vor_flags
|
|
// (0 = OFF, 1 = TO, 2 = FR). Indexed straight into a 3-string
|
|
// table at draw time.
|
|
uint8_t nav1Flag;
|
|
uint8_t nav2Flag;
|
|
} RadiosT;
|
|
|
|
|
|
void radiosInit(RadiosT *r);
|
|
|
|
// Sweep the database for the nearest NAV / ADF / COM to the aircraft
|
|
// and tune each radio to it. Useful for "find me something to listen
|
|
// to" gestures and as a sanity check that the database is populated.
|
|
void radiosTuneToNearest(RadiosT *r, const AircraftT *ac);
|
|
|
|
// Step the named radio's frequency by one BCD click. Stride matches
|
|
// real-radio behaviour: NAV/COM 0.05 MHz, ADF 1 kHz. Updates the
|
|
// active station pointer.
|
|
void radiosStepFreq(RadiosT *r, RadioE which, int direction);
|
|
|
|
// Step the named VOR's OBS course by `deltaDegrees` (signed; will be
|
|
// quantised to a byte-angle delta). NAV1/NAV2 only.
|
|
void radiosStepObs(RadiosT *r, RadioE which, int deltaDegrees);
|
|
|
|
// FS2 BCD per-digit entry. The user types a digit 0..9 and the
|
|
// radio's frequency rotates one decimal slot left, dropping the high
|
|
// digit. Mirrors chunk5 KeyDecreasePatch / KeyIncreasePatch with a
|
|
// fixed digit input.
|
|
void radiosEnterDigit(RadiosT *r, RadioE which, uint8_t digit);
|
|
|
|
// BCD digit-entry mode (FS2 chunk5 InputMode $04..$0F). The caller
|
|
// arms a target radio with `radiosBeginDigitEntry`; subsequent digit
|
|
// keys feed `radiosEnterDigit` until the user clears with
|
|
// `radiosEndDigitEntry`. RADIO_INPUT_NONE means digit keys go to
|
|
// their normal binding (= mode toggles).
|
|
typedef enum RadioInputModeE {
|
|
RADIO_INPUT_NONE = 0,
|
|
RADIO_INPUT_NAV1,
|
|
RADIO_INPUT_NAV2,
|
|
RADIO_INPUT_COM1,
|
|
RADIO_INPUT_ADF
|
|
} RadioInputModeE;
|
|
|
|
// Recompute all derived values (bearings, DME, deflections) from the
|
|
// aircraft's current position and the active station pointers. Call
|
|
// once per frame after the flight integrator.
|
|
void radiosUpdate(RadiosT *r, const AircraftT *ac);
|
|
|
|
// Format a tuned frequency for display. NAV/COM produce "XXX.X" (5
|
|
// chars + null); ADF produces "XXX" (3 chars + null). `out` must be
|
|
// at least 6 bytes.
|
|
void radiosFormatFreq(uint16_t freq, RadioE which, char *out);
|
|
|
|
// Look up a station by (type, freq). Returns NULL if no match.
|
|
// Exposed for tests / tooling; `radiosStepFreq` does this internally.
|
|
const StationDataT *radiosFindStation(char type, uint16_t freq);
|
|
|
|
#endif
|