
struct RxData //DATA STRUCTURE FOR A RECEIVER
{
int Syn; //current position of tuning synchro
int SynHi[3]; //synchro position for highest frequency in each band
int SynLo[3]; //synchro position for lowest frequency in each band
int WB; //currently selected waveband
int Sig; //signal strength delivered by receiver's IF amp
int Tone[3]; //tone levels delivered to receiver's AF stage input
int Valid; //NAV data validation bits
long Frq; //frequency to which receiver is currently tuned
double ISR; //selected inbound VOR radial or ILS runway heading
double OSR; //selected outbound VOR radial
double Brg; //bearing of tuned station from receiver
double RadDev; //deviation of aircraft from selected radial
double StrOff; //required steering offset from station
double ReqHdg; //heading the aircraft must fly
double DistTD; //ILS distance to touch-down
double PrvDst; //dist to/from stn at previous program pass
double HdgErr; //horizontal (VOR/ILS) deviation correction command
double GsErr; //aircraft's ILS glideslope deviation
double DesErr; //difference between required and actual angle of descent
double Atten; //signal attenuation divisor due to receiver being off-tune
BOOL dFrq; //set TRUE by Receivers() when receiver is re-tuned
BOOL capture; //indicates a selected radial has been captured
BOOL OnOff; //receiver's on/off switch
BOOL CctBrk; //receiver's d/c power supply circuit breaker
BOOL SynBrk; //receiver's synchro a/c power supply circuit breaker
struct TxData *t; //pointer to the TxData structure of the
} //dominant currently on-tune station.
*Rx[10]; //Array of pointers to NumRx receiver data structures
To access the Rx[ ] pointer-array efficiently within for() loops we use a secondary array of pointers pRx[ ] which contains pointers to the elements of the Rx[ ] array:

pRx[ ] is declared inside the RxSig() function where it is used exclusively.
The following function determines the signal strength for all receivers of the type which receives the type of station whose TxData is pointed to by 't'. It also calculates the possible separate audio tone levels for each of the three possible pitches of 1020Hz, 1300Hz and 3000Hz.
int RxSig(t) {
int RxType [] = { //Type of Stn received by Type of Rx
0, //0 NDB 0 ADF
0, //1 RRG 0 ADF
1, //2 VOR 1 NAV
1, //3 VOR/DME 1 NAV
1, //4 ILS 1 NAV
1, //5 ILS/DME 1 NAV
1, //6 DME 1 NAV
2, //7 AMK 2 MKR
2, //8 BMK 2 MKR
2, //9 OMK 2 MKR
2, //10 MMK 2 MKR
2 //11 IMK 2 MKR
};
//An array of pointers to pointers to RxData structures
struct RxData **pRx[] = {
Rx, //points to Rx[] element ptg to RxData for ADF1
Rx + 4, //points to Rx[] element ptg to RxData for NAV1
Rx + 8, //points to Rx[] element ptg to RxData for MKR1
Rx + 10 //points to the element beyond end of Rx array
},
*r, //points to RxData struct of rx being dealt with
**rx, //points to element of Rx[] containing 'r'
/*The following pointer points to the element of Rx[]
after the one containing the pointer to last RxData
structure for the type of receiver concerned */
**RX,
/*The following pointer points to the element within pRx[]
(above) which points to the element within Rx[ ] which
points to the RxData structure of the first receiver of
the type which receives the type of station whose TxData
structure is pointed to by 't'. */
***prx = pRx + *( RxType + t->StnType );
for(rx = *prx, RX = *(prx + 1); rx < RX; rx++) { //FOR EACH RECEIVER OF THIS TYPE...
if((r = *rx) > NULL) { //If Rx[rx] contains a ptr to an existing RxData structure..
if(r->dFrq == TRUE) { //If this rx has been re-tuned since the last station scan...
r->dFrq = FALSE; //Cancel 'frequency changed' flag
r->Atten = DeTune(t->Frq, r-Frq); //Get its detuning attenuation divisor
}
/* Get the signal strength of this station at the aircraft
and divide it by the de-tuning attenuation of receiver's
passband. Rescale it from a floating point double to an
interger ranging from 0 to 255. If the resulting signal
is the strongest so far encountered during this station
scan THEN set it as receiver's current signal strength,
and set this station as dominant on-tune station. */
if((Sig = (int)(255 * TxSig(t)/r->Atten)) > r->Sig) {
r->Sig = Sig; r->t = t;
/*If the station's Morse key is down, and this is the
strongest station keying at this pitch, make this the
sound level for this pitch of tone. */
if((t->MorseKey == TRUE)&&(r->Tone[t->pitch] < Sig))
r->Tone[t->pitch] = Sig;
}
}
}
}
This function checks each receiver's on/off switch and dc power circuit breaker and then determines the frequency to which it is currently tuned. If the receiver has been retuned since the last pass, the new frequency is stored and a 'frequency changed' flag is set in the receiver's RxData structure. If the receiver is switched off or its circuit breaker is out, its frequency is set to zero. The signal and tone levels of all receivers are reset to zero ready for the next station scan.
RxInput() {
long(*GetFrq[])(struct RxData *) = {
ADFfrq, ADFfrq, //function returning ADF rx frequency
ADFfrq, ADFfrq,
NAVfrq, NAVfrq, //function returning NAV rx frequency
NAVfrq, NAVfrq,
MKRfrq,MKRfrq //function returning Marker frequency
};
struct RxData *r; //points to RxData of current rx
**rx; //ptr to Rx[] element holding 'r'
**RX = Rx + 10;
static int r = 0; //element number of Rx[] range 0 to 9
long frq; //current receiver frequency
register n = 0; //element number of Rx[]
for(rx = Rx; rx <= RX; rx++, n++) //for all receivers
{
if((r = *rx) > NULL) //if an rx installed in this 'position'
{
if(r->CctBrk == TRUE && r->OnOff == TRUE) { //if rx's dc circuit breaker closed and rx is switched on
if((frq = (*(GetFrq + rx))(r)) != r->Frq) { //if receiver has been retuned
r->Frq = frq; //store new frequency
r->dFrq = TRUE; //indicate that it has changed
}
}
else r->Frq = 0; //frequency = 0 means rx inoperative
}
r->Sig = 0; //clear the dominant signal strength
for(register x = 0; x < 3; x++)
r->Tone[x] = 0; //clear the Morse tone levels
}
}
Whenever a station's Morse tone duration timer expires, the Transmitters() function reloads the station's Morse tone duration timer with the duration of the next dot, dash, inter-element, inter-letter or delay specified in its callsign string and flips the state of the Morse key from tone-on to tone-off or vice versa. This function should be called roughly every 200 milliseconds.
TxScan() { //NAVIGATION STATION SCANNER
static double Sigma, InvDst; //For computing height of
static int N; //ground under aircraft.
static struct TxData **tx; //Pointer to an element in
//Tx[ ] pointer array.
struct TxData *t; //Pointer to a TxData (ie a
//station data) structure.
for(tx = Tx; tx <= TxHi; tx++) { //for each element in the Tx[] pointer array
/*If it contains a pointer to a TxData structure
and if it is the end of current Morse element
then first reverse the state of the Morse key. */
if(((t = *tx) > NULL) && (--(t->MorseTimer) < 0)) {
t->MorseKey = !(t->MorseKey);
/*if we've reached the end of the current sequence of
dots and dashes then first reset the pointer to the
start of the Morse Code buffer. */
if(*(t->pMorse) == '\0') {
t->pMorse = t->Morse;
/*If the station has a multiple and if it has been
repeated the required number of times, then get
the next part of the call sign. */
if(t->Single == FALSE) && ((--(t->Repeat) < 0))
SetUpCallSign(t);
}
//Set timer to the duration of the next dash or dot
t->MorseTimer = *(t->pMorse)++;
}
RxSig(t); //compute the station's signal for each receiver
/*If the station is an ILS or an ILS/DME then add in the
inverse of the station's distance from the aircraft and
the inverse of their height differences divided by the
distance between them. Note: (--(t->Repeat) < 0) above
avoids the possibility of a division by zero error. */
if((t->StnType == 4 || t->StnType == 5) && (t->Dst > 0)) {
InvDst += 1 / t->Dst; //add inverse dist
Sigma += t->Ht / t->Dst; //add dist/height
}
}
//Compute estimated height of ground beneath aircraft
Air.GndHt = Sigma / (N * InvDst);
}