/*********************************************************************** * * * Program to control LORAN-C radio * * * * Header file used by all programs * * * * Note on units: (ms) milliseconds, (us) microseconds, (cycle) 10-us * * carrier cycles, (clock) 200-ns master clock cycles * * * *********************************************************************** */ #include #include #include #include #include #include #define DEBUG /* define for simulation */ /* * Sizes of things. The pulse-group filter is a shift register with one * stage for each 100-us bin in a 900-us sample window plus one stage * for a noise gate for a total of 10 stages. The envelope filters * consist of one stage for each 10-us cycle in the 400-us envelope * gate, for a total of 40 stages. */ #define NSTA 6 /* max number of stations */ #define NRMS 10 /* size of pulse-group filter */ #define NENV 40 /* size of envelope filter */ #define RMAX 20 /* size of rank vector */ #define NLMS 9 /* size of LMS filter (not used) */ /* * Incidental constants. These establish the master clock period, LORAN- * C carrier cycle period, the velocity of light and other trivia. */ #define CLOCK 50 /* clock period (clock) */ #define CYCLE 10 /* carrier period (us) */ #define GRI 800 /* pulse-group gate (cycle) */ #define PCX (NENV * CLOCK) /* envelope gate (clock) */ #define STROBE 50 /* strobe gate (clock) */ #define PI 3.141592653589 /* the real thing */ #define PIH (PI / 2) /* half the real thing */ #define PID (2 * PI) /* twice the real thing */ #define D2R (PI / 180) /* convert degrees to radians */ #define R2D (180 / PI) /* convert radians to degrees */ #define VOFL 2.9979250e8 /* velocity of light */ #define R 6371.2 /* radius of the Earth (km) */ #define LORSTA "loran.dat" /* name of LORAN-C data file */ /* * The program and display guard times bound the maximum latency for the * program to process samples at the end of a gri and for the output * routines to display a line, respectively. The LORAN-C signal * specification requires a minimum guard time of 9900 microseconds or * 990 cycles, which is less than the value here (1100). The reason for * this is that the 386/387 is not quite fast enough to meet the spec; * however, this has not been a problem in the prototype system. If the * time to the next gri is less than either of these, the next frame is * skipped. The watchdog timeout is the maximum number of frames before * the program abandons cycle search and reverts to pulse-group search. */ #define PGUARD 1100 /* program guard time (cycle) (990!) */ #define DGUARD 8000 /* display guard time (cycle) */ #define WATCHDOG 2000 /* watchdog timeout (frame) */ /* * The i-channel and q-channel median filters are characterized by the * shift-register size (mcnt). The minimum value of this variable * (PMIN) is established at the conclusion of the pulse-group search and * must be at least 3. As the time constant of integration is increased * during the subsequent synchronization process, mcnt can be increased * to improve the efficience of the filter. However, its size (sample * delay) must remain small compared with the time constant of * integration in order to preserve the transient response of the * feedback loop. The maximum value of mcnt (MMAX) controls the high- * frequency response (boxcar effect) of the filter and is * experimentally determined. The boxcar affect is mitigated somewhat by * the use of a trimmed-mean statistic, where the output of the filter * is actually the average of the three samples near the median of the * (sorted) samples in the filter. */ #define MMIN 3 /* min median filter size */ #define MMAX 7 /* max median filter size */ /* * The amplitude and phase feedback loops are characterized by the time * constant of integration (pfac). The minimum value of this variable * (PMIN) establishes the bandwidth of the phase loop and thus the pull- * in range. There is a tradeoff between pull-in range and sensitivity; * the larger the pull-in range, and thus the larger the master * oscillator intrinsic frequency tolerance, the greater the minimum * signal required for synchronization and vice versa. The value * selected for PMIN is appropriate for an oscillator tolerance of 0.1 * ppm, pretty tight for a cold rock, but about right for a hot one. The * maximum value of pfac (PMAX) establishes the tracking range, which * depends on the intrinsic short-term stability (wander) of the master * oscillator. If this is made too large, the phase loop can break lock * if the wander is too large. The value selected seems adequate for the * hot rock now used (Isotemp); however, the wander of this unit has not * been precisely determined. The speed of adaptation of the amplitude * and phase loops is established by the PFAC parameter, which has been * experimentally determined by simulation and watching many * sunchronization episodes under varying conditions. */ #define PMIN 8 /* min pll time constant */ #define PMAX 1000 /* max pll time constant */ #define PFAC 1.2 /* time-constant adjustment factor */ /* * The agc adjustment factor controls the gain of the amplitude feedback * loop. There is some hocus-pocus here, since the transfer function of * the gain-control loop has not been precisely determined. The value is * selected so that the agc action is smooth and free of obvious * hunting. */ #define AFAC 4 /* agc adjustment factor */ /* * The OFFSET parameter represents the delay of the matched filter and * noise gate to position the pulse group in the middle of the pulse- * group gate. The delay from the peak of the matched filter to the * current sample is 550 microseconds (55 cycles). To this is added the * delay necessary to position the pulse group at the center of the 400- * us pulse-group gate at the conclusion of pulse-group search, or 200 * us (20 cycles). Experimentally, for whatever reason, the optimum * value is found to be 12 instead of 20. Note that the pulse-group gate * and phase decoder are implemented between the first and second rf * stages and operate with a relatively wide passband, while the strobe * is implemented as part of the synchronous detector and operates with * a relatively narrow passband. The additional delay due to bandwidth * reduction is specified by the RCVDELAY parameter. From SPICE * simulation this value is found to be between 20 and 40 us; but, in * practice, it must be experimentally determined relative to a * precision timing source, such as a GPS receiver. */ #define OFFSET (55 + 12) /* pulse-group offset (cycle) */ #define RCVDELAY 30 /* receiver strobe delay (us) */ /* * The VCO parameter represents the initial value of the vco dac and is * set at the midpoint of its full-scale range. A vernier pot on the * master oscillator unit is then adjusted for zero nominal frequency * offset as much less than 0.1 ppm as possible (for the Istemp rock, * down in the 1e-10 range). The AGC parameter represents the initial * value of the agc dac and thus the gain of the system during pulse- * group search. It is set with the antenna connected using the operator * commands to increment or decrement the agc until the peak of the * maximum amplitude pulses observed with an oscilloscope connected to * the output of the last rf stage preceeding the detector is nominally * 800 mV p-p. The ADCOFS parameter represents the initial coarse * offsets of the adc channels and is chosen to match the reference * voltage of the integrators. The working offsets are refined by the * program. */ #define VCO 2048 /* initial vco dac (0 V)*/ #define AGC 1440 /* initial agc dac (3.51 V) */ #define ADCOFS (256 * 3 / 5) /* adc offset for 3V Zener */ /* * The XGATE parameter establishs the error/false-alarm rate during the * pulse-group search mode. A noise gate nips ambient pulse-type * electrical noise and isolated pulses from other loran chains during * the pulse-group search. The value is experimentally determined as a * tradeoff between clipping wanted pulses, thus possibly failing to * synchronize, and allowing unwanted pulses, thus possibly synchonizing * in error. The value selected does reasonably well in simulations * using Gaussian noise; however, it is likely the optimum value under * actual LORAN-C conditions may be considerably different and open to * experimental refinement. */ #define XGATE 4. /* cross-rate noise gate */ /* * The following parameters establish the error/false-alarm rate during * the cycle-search and tracking modes and are determined experimentally * during simulation and refined during actual operation. The values * selected were established using an initial frequency offset of 0.1 * ppm and a received peak-signal/Gaussian-noise ratio (snr) of 0 dB * (with no coding gain), which is comfortably heroic. The envelope- * cycle-difference (ecd) snr gate EGATE and strobe noise gate SGATE * control entry to the tracking mode from the cycle-search mode. The * EGATE parameter establishes the minimum snr acceptable for tracking * mode. If set too low the system may synchronize to casual pulses or * random noise; if set too high the system may never track a legitimate * station. The SGATE parameter represents the maximum acceptable span * between the maximim cycle number and minimum cycle number of the * strobe (reference) cycle determined in the last several envelope * scans. It is chosen to minimize the frequency of 10-us strobe slips * due to noise excursions. If set too low this frequency may be * unneccessarily high; if set too high the "boxcar" effect of large * noise excursions may unneccessarily extend the period of incorrect * synchronization. The phase error gate PGATE controls the adjustment * of the time constant of integration (pfac) during the initial cycle- * search and tracking phases. With high noise levels at initial entry * to the cycle-search mode, the phase and amplitude loops are quite * loose and bounce around a lot. However, once reliable phase lock has * been achieved and the reference cycle has been found, the time * constant of integration must be increased by two orders of magnitude * in order to achieve the ultimate stability and accuracy. In order to * quickly reach this condition, PGATE needs to be set as high as * possible; however, this may inhibit and even defeat the initial * adjustments necessary to compensate for the master oscillator * intrinsic frequency tolerance. The value selected allows some 90% of * the initial adjustment to be completed before the time constant is * incremented, yet provides reliable adaptation under the simulated * conditions. */ #define EGATE .7 /* ecd snr gate */ #define SGATE 2 /* strobe noise gate */ #define PGATE 150 /* phase error gate */ /* * Phase-lock loop (pll) parameters (the trickiest of all). The receiver * agc is controlled to produce a max envelope-cycle amplitude of 100, * which represents a phase-detector constant Kd = 100 * 2 * PI = 628. * This is an upper bound; since, when locked only the third carrier * cycle is used and its anplitude is only about 50. The vco has a * measured sensitivity Ko = 2.25e-10 per Hz or 2.25e-5 at the 100-kHz * phase-detector frequency. The overall pll gain is the product Kd * * Ko. The digital loop gain is found experimentally to control slave- * loop dynamics. */ #define Kd 628. /* phase detector constant */ #define Ko 2.25e-5 /* vco constant (Hz/dac unit) */ #define VGAIN (Kd * Ko) /* overall analog loop gain */ #define DGAIN 15 /* digital loop threshold */ /* * The following represent works in progress. */ #define LMS 1e-5 /* LMS step size (not used) */ #define AGCFAC 16 /* agc time constant (not used) */ /* * Define program modes */ #define MODE_MIN 1 /* set min gain */ #define MODE_MAX 2 /* set max gain */ #define MODE_AGC 3 /* set agc */ #define MODE_PSRCH 4 /* pulse-group search */ #define MODE_CSRCH 5 /* cycle search */ #define MODE_TRACK 6 /* phase track */ /* * Timing generator definitions and master oscillator source */ #define PORT 0x0300 /* controller port address */ #define TGC PORT+0 /* stc control port (r/w) */ #define TGD PORT+1 /* stc data port (r/w) */ #define OSC 0x0500 /* oscillator: 0x0100 int/0x0500 ext */ /* * Analog/digital converter (ADC) hardware definitions */ #define ADC PORT+2 /* adc buffer (r)/address (w) */ #define ADCGO PORT+3 /* adc status (r)/adc start (w) */ #define START 0x01 /* converter start bit (w) */ #define BUSY 0x01 /* converter busy bit (r) */ #define DONE 0x80 /* converter done bit (r) */ #define I 0 /* i channel (phase) */ #define Q 1 /* q channel (amplitude) */ #define S 2 /* s channel (agc) */ /* * Digital/analog converter (DAC) hardware definitions * Note: output voltage increases with value programmed; the buffer * is loaded in two 8-bit bytes, the lsb 8 bits with the MSB bit off in * the PAR register, the msb 4 bits with the MSB on. */ #define DACA PORT+4 /* vco (dac a) buffer (w) */ #define DACB PORT+5 /* agc (dac b) buffer (w) */ /* * Pulse-code generator (CODE) hardware definitions * Note: bits are shifted out from the lsb first */ #define CODE PORT+6 /* pulse-code buffer (w) */ #define MPCA 0xCA /* LORAN-C master pulse code group a */ #define MPCB 0x9F /* LORAN-C master pulse code group b */ #define SPCA 0xF9 /* LORAN-C slave pulse code group a */ #define SPCB 0xAC /* LORAN-C slave pulse code group b */ /* * Mode register (PAR) hardware definitions */ #define PAR PORT+7 /* parameter buffer (w) */ #define INTEG 0x03 /* integrator mask */ /* * time constant values * * 0 1.000 ms * 1 0.264 ms * 2 0.036 ms * 3 short caps */ #define GATE 0x0C /* gate source mask */ /* * gate source values * * 4 always open * 8 group repeition interval (GRI) * c puldse code interval (PCI) * f strobe (STB) */ #define MSB 0x10 /* load dac high-order bits */ #define IEN 0x20 /* enable interrupt bit */ #define EN5 0x40 /* enable counter 5 bit */ #define ENG 0x80 /* enable gri bit */ /* * Timing generator (STC) hardware commands */ /* argument sssss = counter numbers 5-1 */ #define LOADDP 0x00 /* load data pointer */ /* argument ee = element (all groups except ggg = 000 or 111) */ #define MODEREG 0x00 /* mode register */ #define LOADREG 0x08 /* load register */ #define HOLDREG 0x10 /* hold register */ #define HOLDINC 0x18 /* hold register (hold cycle increm) */ /* argument ee = element (group ggg = 111) */ #define ALARM1 0x07 /* alarm register 1 */ #define ALARM2 0x0F /* alarm register 2 */ #define MASTER 0x17 /* master mode register */ #define STATUS 0x1F /* status register */ #define ARM 0x20 /* arm counters */ #define LOAD 0x40 /* load counters */ #define LOADARM 0x60 /* load and arm counters */ #define DISSAVE 0x80 /* disarm and save counters */ #define SAVE 0xA0 /* save counters */ #define DISARM 0xC0 /* disarm counters */ /* argument nnn = counter number */ #define SETTOG 0xE8 /* set toggle output HIGH for counter */ #define CLRTOG 0xE0 /* set toggle output LOW for counter */ #define STEP 0xF0 /* step counter */ /* argument eeggg, where ee = element, ggg - counter group */ /* no arguments */ #define ENABDPS 0xE0 /* enable data pointer sequencing */ #define ENABFOUT 0xE6 /* enable fout */ #define ENAB8 0xE7 /* enable 8-bit data bus */ #define DSABDPS 0xE8 /* disable data pointer sequencing */ #define ENAB16 0xEF /* enable 16-bit data bus */ #define DSABFOUT 0xEE /* disable fout */ #define ENABPFW 0xF8 /* enable prefetch for write */ #define DSABPFW 0xF9 /* disable prefetch for write */ #define RESET 0xFF /* master reset */ /* * The station structure is the main data structure used by the program. * There is one of these for every station in the chain up to five. It * contains raw and processed signal samples plus signals used for * acquisition, tracking and control of the program. */ struct station { /* * Identification and control information */ char type; /* type (m, w, x, y, z) */ int mode; /* operating mode (1-6) */ int codesw; /* gri a/b switch */ int index; /* index (1-5) */ /* * Cycle-adjustment counters and related riffraff */ long phase; /* station phase offset (cycle) */ int mindex; /* index of max pulse-group signal */ int maxdex; /* index of max cycle in envelope */ int cycle; /* cycle counter */ int strobe; /* offset to reference cycle (cycle) */ int env; /* envelope scan pointer */ int envbot; /* first cycle in envelope scan */ int envtop; /* last cycle in envelope scan */ int ptrenv; /* display cycle */ int sgate; /* strobe noise (max-min) */ int count; /* utility counter */ int icnt; /* integration cycle counter */ int mcnt; /* median counter */ int ecnt; /* envelope counter */ /* * Received signal samples and time constants */ int isig; /* i-signal (a+b) (adc chan 0) */ int qsig; /* q-signal (a+b) (adc chan 1) */ double fmax; /* max signal */ double fmin; /* min signal */ double level; /* gain control */ double pfac; /* integration time constant */ /* * Phase-lock loop variables */ double vphase; /* pll phase adjustment */ double vfreq; /* pll frequency adjustment */ double update; /* time of last pll update (us) */ int slew; /* digital pll adjustment (clock) */ int borrow; /* slew overflow (clock) */ /* * Median filters, shift registers and cycle accumulators */ int stb[MMAX]; /* strobe median filter */ double rms[NRMS]; /* pulse-group shift register */ double pmed[NENV][MMAX]; /* phase median filter */ double emed[NENV][MMAX]; /* envelope median filter */ double pcyc[NENV]; /* cycle phase (i channel) */ double ecyc[NENV]; /* cycle amplitude (q channel) */ double qcyc[NENV]; /* cycle energy (q channel) */ double erms[NENV]; /* cycle rms error */ double lms[NENV]; /* output signal for LMS algorithm */ double weight[NLMS]; /* weight vector for LMS algorithm */ /* * Signal quality indicators */ double esnr; /* estimated ecd snr */ double rsnr; /* estimated reference cycle snr */ double psnr; /* estimated phase error */ /* * Debugging data and status-message area */ int cscnt; /* cycle-slip events */ int sscnt; /* strobe-slip events */ int pncnt; /* cross-rate noise events */ char kbd; /* last keyboard twink */ char msg[80]; /* status message */ char report[80]; /* report string for display */ /* * LORAN-C station data (from data file) */ double lat; /* north latitude (rad) */ double lon; /* west longitude (rad) */ double rad_power; /* radiated power (kw) */ char name[40]; /* station location name */ double rcvr_azim; /* receiver azimuth (rad) */ double xmtr_azim; /* transmitter azimuth (rad) */ double ems_delay; /* emission delay (us) */ double path_delay; /* path delay (us) */ double system_delay; /* computed loran system delay (us) */ }; /* end header */