Home | History | Annotate | Line # | Download | only in ntpd
refclock_wwv.c revision 1.1.1.1.6.1
      1  1.1.1.1.6.1    yamt /*	$NetBSD: refclock_wwv.c,v 1.1.1.1.6.1 2014/05/22 15:50:09 yamt Exp $	*/
      2          1.1  kardel 
      3          1.1  kardel /*
      4          1.1  kardel  * refclock_wwv - clock driver for NIST WWV/H time/frequency station
      5          1.1  kardel  */
      6          1.1  kardel #ifdef HAVE_CONFIG_H
      7          1.1  kardel #include <config.h>
      8          1.1  kardel #endif
      9          1.1  kardel 
     10          1.1  kardel #if defined(REFCLOCK) && defined(CLOCK_WWV)
     11          1.1  kardel 
     12          1.1  kardel #include "ntpd.h"
     13          1.1  kardel #include "ntp_io.h"
     14          1.1  kardel #include "ntp_refclock.h"
     15          1.1  kardel #include "ntp_calendar.h"
     16          1.1  kardel #include "ntp_stdlib.h"
     17          1.1  kardel #include "audio.h"
     18          1.1  kardel 
     19          1.1  kardel #include <stdio.h>
     20          1.1  kardel #include <ctype.h>
     21          1.1  kardel #include <math.h>
     22          1.1  kardel #ifdef HAVE_SYS_IOCTL_H
     23          1.1  kardel # include <sys/ioctl.h>
     24          1.1  kardel #endif /* HAVE_SYS_IOCTL_H */
     25          1.1  kardel 
     26          1.1  kardel #define ICOM 1
     27          1.1  kardel 
     28          1.1  kardel #ifdef ICOM
     29          1.1  kardel #include "icom.h"
     30          1.1  kardel #endif /* ICOM */
     31          1.1  kardel 
     32          1.1  kardel /*
     33          1.1  kardel  * Audio WWV/H demodulator/decoder
     34          1.1  kardel  *
     35          1.1  kardel  * This driver synchronizes the computer time using data encoded in
     36          1.1  kardel  * radio transmissions from NIST time/frequency stations WWV in Boulder,
     37          1.1  kardel  * CO, and WWVH in Kauai, HI. Transmissions are made continuously on
     38          1.1  kardel  * 2.5, 5, 10 and 15 MHz from WWV and WWVH, and 20 MHz from WWV. An
     39          1.1  kardel  * ordinary AM shortwave receiver can be tuned manually to one of these
     40          1.1  kardel  * frequencies or, in the case of ICOM receivers, the receiver can be
     41          1.1  kardel  * tuned automatically using this program as propagation conditions
     42          1.1  kardel  * change throughout the weasons, both day and night.
     43          1.1  kardel  *
     44          1.1  kardel  * The driver requires an audio codec or sound card with sampling rate 8
     45          1.1  kardel  * kHz and mu-law companding. This is the same standard as used by the
     46          1.1  kardel  * telephone industry and is supported by most hardware and operating
     47          1.1  kardel  * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
     48          1.1  kardel  * implementation, only one audio driver and codec can be supported on a
     49          1.1  kardel  * single machine.
     50          1.1  kardel  *
     51          1.1  kardel  * The demodulation and decoding algorithms used in this driver are
     52          1.1  kardel  * based on those developed for the TAPR DSP93 development board and the
     53          1.1  kardel  * TI 320C25 digital signal processor described in: Mills, D.L. A
     54          1.1  kardel  * precision radio clock for WWV transmissions. Electrical Engineering
     55          1.1  kardel  * Report 97-8-1, University of Delaware, August 1997, 25 pp., available
     56          1.1  kardel  * from www.eecis.udel.edu/~mills/reports.html. The algorithms described
     57          1.1  kardel  * in this report have been modified somewhat to improve performance
     58          1.1  kardel  * under weak signal conditions and to provide an automatic station
     59          1.1  kardel  * identification feature.
     60          1.1  kardel  *
     61          1.1  kardel  * The ICOM code is normally compiled in the driver. It isn't used,
     62          1.1  kardel  * unless the mode keyword on the server configuration command specifies
     63          1.1  kardel  * a nonzero ICOM ID select code. The C-IV trace is turned on if the
     64          1.1  kardel  * debug level is greater than one.
     65          1.1  kardel  *
     66          1.1  kardel  * Fudge factors
     67          1.1  kardel  *
     68  1.1.1.1.6.1    yamt  * Fudge flag4 causes the debugging output described above to be
     69          1.1  kardel  * recorded in the clockstats file. Fudge flag2 selects the audio input
     70          1.1  kardel  * port, where 0 is the mike port (default) and 1 is the line-in port.
     71          1.1  kardel  * It does not seem useful to select the compact disc player port. Fudge
     72          1.1  kardel  * flag3 enables audio monitoring of the input signal. For this purpose,
     73          1.1  kardel  * the monitor gain is set to a default value.
     74          1.1  kardel  *
     75          1.1  kardel  * CEVNT_BADTIME	invalid date or time
     76          1.1  kardel  * CEVNT_PROP		propagation failure - no stations heard
     77          1.1  kardel  * CEVNT_TIMEOUT	timeout (see newgame() below)
     78          1.1  kardel  */
     79          1.1  kardel /*
     80          1.1  kardel  * General definitions. These ordinarily do not need to be changed.
     81          1.1  kardel  */
     82          1.1  kardel #define	DEVICE_AUDIO	"/dev/audio" /* audio device name */
     83          1.1  kardel #define	AUDIO_BUFSIZ	320	/* audio buffer size (50 ms) */
     84          1.1  kardel #define	PRECISION	(-10)	/* precision assumed (about 1 ms) */
     85          1.1  kardel #define	DESCRIPTION	"WWV/H Audio Demodulator/Decoder" /* WRU */
     86  1.1.1.1.6.1    yamt #define WWV_SEC		8000	/* second epoch (sample rate) (Hz) */
     87  1.1.1.1.6.1    yamt #define WWV_MIN		(WWV_SEC * 60) /* minute epoch */
     88          1.1  kardel #define OFFSET		128	/* companded sample offset */
     89          1.1  kardel #define SIZE		256	/* decompanding table size */
     90          1.1  kardel #define	MAXAMP		6000.	/* max signal level reference */
     91          1.1  kardel #define	MAXCLP		100	/* max clips above reference per s */
     92          1.1  kardel #define MAXSNR		40.	/* max SNR reference */
     93          1.1  kardel #define MAXFREQ		1.5	/* max frequency tolerance (187 PPM) */
     94          1.1  kardel #define DATCYC		170	/* data filter cycles */
     95          1.1  kardel #define DATSIZ		(DATCYC * MS) /* data filter size */
     96          1.1  kardel #define SYNCYC		800	/* minute filter cycles */
     97          1.1  kardel #define SYNSIZ		(SYNCYC * MS) /* minute filter size */
     98          1.1  kardel #define TCKCYC		5	/* tick filter cycles */
     99          1.1  kardel #define TCKSIZ		(TCKCYC * MS) /* tick filter size */
    100          1.1  kardel #define NCHAN		5	/* number of radio channels */
    101          1.1  kardel #define	AUDIO_PHI	5e-6	/* dispersion growth factor */
    102          1.1  kardel #define	TBUF		128	/* max monitor line length */
    103          1.1  kardel 
    104          1.1  kardel /*
    105          1.1  kardel  * Tunable parameters. The DGAIN parameter can be changed to fit the
    106          1.1  kardel  * audio response of the radio at 100 Hz. The WWV/WWVH data subcarrier
    107          1.1  kardel  * is transmitted at about 20 percent percent modulation; the matched
    108          1.1  kardel  * filter boosts it by a factor of 17 and the receiver response does
    109          1.1  kardel  * what it does. The compromise value works for ICOM radios. If the
    110          1.1  kardel  * radio is not tunable, the DCHAN parameter can be changed to fit the
    111          1.1  kardel  * expected best propagation frequency: higher if further from the
    112          1.1  kardel  * transmitter, lower if nearer. The compromise value works for the US
    113          1.1  kardel  * right coast.
    114          1.1  kardel  */
    115          1.1  kardel #define DCHAN		3	/* default radio channel (15 Mhz) */
    116          1.1  kardel #define DGAIN		5.	/* subcarrier gain */
    117          1.1  kardel 
    118          1.1  kardel /*
    119          1.1  kardel  * General purpose status bits (status)
    120          1.1  kardel  *
    121          1.1  kardel  * SELV and/or SELH are set when WWV or WWVH have been heard and cleared
    122          1.1  kardel  * on signal loss. SSYNC is set when the second sync pulse has been
    123          1.1  kardel  * acquired and cleared by signal loss. MSYNC is set when the minute
    124          1.1  kardel  * sync pulse has been acquired. DSYNC is set when the units digit has
    125          1.1  kardel  * has reached the threshold and INSYNC is set when all nine digits have
    126          1.1  kardel  * reached the threshold. The MSYNC, DSYNC and INSYNC bits are cleared
    127          1.1  kardel  * only by timeout, upon which the driver starts over from scratch.
    128          1.1  kardel  *
    129          1.1  kardel  * DGATE is lit if the data bit amplitude or SNR is below thresholds and
    130          1.1  kardel  * BGATE is lit if the pulse width amplitude or SNR is below thresolds.
    131          1.1  kardel  * LEPSEC is set during the last minute of the leap day. At the end of
    132          1.1  kardel  * this minute the driver inserts second 60 in the seconds state machine
    133          1.1  kardel  * and the minute sync slips a second.
    134          1.1  kardel  */
    135          1.1  kardel #define MSYNC		0x0001	/* minute epoch sync */
    136          1.1  kardel #define SSYNC		0x0002	/* second epoch sync */
    137          1.1  kardel #define DSYNC		0x0004	/* minute units sync */
    138          1.1  kardel #define INSYNC		0x0008	/* clock synchronized */
    139          1.1  kardel #define FGATE		0x0010	/* frequency gate */
    140          1.1  kardel #define DGATE		0x0020	/* data pulse amplitude error */
    141          1.1  kardel #define BGATE		0x0040	/* data pulse width error */
    142          1.1  kardel #define	METRIC		0x0080	/* one or more stations heard */
    143          1.1  kardel #define LEPSEC		0x1000	/* leap minute */
    144          1.1  kardel 
    145          1.1  kardel /*
    146          1.1  kardel  * Station scoreboard bits
    147          1.1  kardel  *
    148          1.1  kardel  * These are used to establish the signal quality for each of the five
    149          1.1  kardel  * frequencies and two stations.
    150          1.1  kardel  */
    151          1.1  kardel #define SELV		0x0100	/* WWV station select */
    152          1.1  kardel #define SELH		0x0200	/* WWVH station select */
    153          1.1  kardel 
    154          1.1  kardel /*
    155          1.1  kardel  * Alarm status bits (alarm)
    156          1.1  kardel  *
    157          1.1  kardel  * These bits indicate various alarm conditions, which are decoded to
    158          1.1  kardel  * form the quality character included in the timecode.
    159          1.1  kardel  */
    160          1.1  kardel #define CMPERR		0x1	/* digit or misc bit compare error */
    161          1.1  kardel #define LOWERR		0x2	/* low bit or digit amplitude or SNR */
    162          1.1  kardel #define NINERR		0x4	/* less than nine digits in minute */
    163          1.1  kardel #define SYNERR		0x8	/* not tracking second sync */
    164          1.1  kardel 
    165          1.1  kardel /*
    166          1.1  kardel  * Watchcat timeouts (watch)
    167          1.1  kardel  *
    168          1.1  kardel  * If these timeouts expire, the status bits are mashed to zero and the
    169          1.1  kardel  * driver starts from scratch. Suitably more refined procedures may be
    170          1.1  kardel  * developed in future. All these are in minutes.
    171          1.1  kardel  */
    172          1.1  kardel #define ACQSN		6	/* station acquisition timeout */
    173          1.1  kardel #define DATA		15	/* unit minutes timeout */
    174          1.1  kardel #define SYNCH		40	/* station sync timeout */
    175          1.1  kardel #define PANIC		(2 * 1440) /* panic timeout */
    176          1.1  kardel 
    177          1.1  kardel /*
    178          1.1  kardel  * Thresholds. These establish the minimum signal level, minimum SNR and
    179          1.1  kardel  * maximum jitter thresholds which establish the error and false alarm
    180          1.1  kardel  * rates of the driver. The values defined here may be on the
    181          1.1  kardel  * adventurous side in the interest of the highest sensitivity.
    182          1.1  kardel  */
    183          1.1  kardel #define MTHR		13.	/* minute sync gate (percent) */
    184          1.1  kardel #define TTHR		50.	/* minute sync threshold (percent) */
    185          1.1  kardel #define AWND		20	/* minute sync jitter threshold (ms) */
    186          1.1  kardel #define ATHR		2500.	/* QRZ minute sync threshold */
    187          1.1  kardel #define ASNR		20.	/* QRZ minute sync SNR threshold (dB) */
    188          1.1  kardel #define QTHR		2500.	/* QSY minute sync threshold */
    189          1.1  kardel #define QSNR		20.	/* QSY minute sync SNR threshold (dB) */
    190          1.1  kardel #define STHR		2500.	/* second sync threshold */
    191          1.1  kardel #define	SSNR		15.	/* second sync SNR threshold (dB) */
    192          1.1  kardel #define SCMP		10 	/* second sync compare threshold */
    193          1.1  kardel #define DTHR		1000.	/* bit threshold */
    194          1.1  kardel #define DSNR		10.	/* bit SNR threshold (dB) */
    195          1.1  kardel #define AMIN		3	/* min bit count */
    196          1.1  kardel #define AMAX		6	/* max bit count */
    197          1.1  kardel #define BTHR		1000.	/* digit threshold */
    198          1.1  kardel #define BSNR		3.	/* digit likelihood threshold (dB) */
    199          1.1  kardel #define BCMP		3	/* digit compare threshold */
    200          1.1  kardel #define	MAXERR		40	/* maximum error alarm */
    201          1.1  kardel 
    202          1.1  kardel /*
    203          1.1  kardel  * Tone frequency definitions. The increments are for 4.5-deg sine
    204          1.1  kardel  * table.
    205          1.1  kardel  */
    206  1.1.1.1.6.1    yamt #define MS		(WWV_SEC / 1000) /* samples per millisecond */
    207  1.1.1.1.6.1    yamt #define IN100		((100 * 80) / WWV_SEC) /* 100 Hz increment */
    208  1.1.1.1.6.1    yamt #define IN1000		((1000 * 80) / WWV_SEC) /* 1000 Hz increment */
    209  1.1.1.1.6.1    yamt #define IN1200		((1200 * 80) / WWV_SEC) /* 1200 Hz increment */
    210          1.1  kardel 
    211          1.1  kardel /*
    212          1.1  kardel  * Acquisition and tracking time constants
    213          1.1  kardel  */
    214          1.1  kardel #define MINAVG		8	/* min averaging time */
    215          1.1  kardel #define MAXAVG		1024	/* max averaging time */
    216          1.1  kardel #define FCONST		3	/* frequency time constant */
    217          1.1  kardel #define TCONST		16	/* data bit/digit time constant */
    218          1.1  kardel 
    219          1.1  kardel /*
    220          1.1  kardel  * Miscellaneous status bits (misc)
    221          1.1  kardel  *
    222          1.1  kardel  * These bits correspond to designated bits in the WWV/H timecode. The
    223          1.1  kardel  * bit probabilities are exponentially averaged over several minutes and
    224          1.1  kardel  * processed by a integrator and threshold.
    225          1.1  kardel  */
    226          1.1  kardel #define DUT1		0x01	/* 56 DUT .1 */
    227          1.1  kardel #define DUT2		0x02	/* 57 DUT .2 */
    228          1.1  kardel #define DUT4		0x04	/* 58 DUT .4 */
    229          1.1  kardel #define DUTS		0x08	/* 50 DUT sign */
    230          1.1  kardel #define DST1		0x10	/* 55 DST1 leap warning */
    231          1.1  kardel #define DST2		0x20	/* 2 DST2 DST1 delayed one day */
    232          1.1  kardel #define SECWAR		0x40	/* 3 leap second warning */
    233          1.1  kardel 
    234          1.1  kardel /*
    235          1.1  kardel  * The on-time synchronization point is the positive-going zero crossing
    236          1.1  kardel  * of the first cycle of the 5-ms second pulse. The IIR baseband filter
    237          1.1  kardel  * phase delay is 0.91 ms, while the receiver delay is approximately 4.7
    238          1.1  kardel  * ms at 1000 Hz. The fudge value -0.45 ms due to the codec and other
    239          1.1  kardel  * causes was determined by calibrating to a PPS signal from a GPS
    240          1.1  kardel  * receiver. The additional propagation delay specific to each receiver
    241          1.1  kardel  * location can be  programmed in the fudge time1 and time2 values for
    242          1.1  kardel  * WWV and WWVH, respectively.
    243          1.1  kardel  *
    244          1.1  kardel  * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
    245          1.1  kardel  * generally within .02 ms short-term with .02 ms jitter. The long-term
    246          1.1  kardel  * offsets vary up to 0.3 ms due to ionosperhic layer height variations.
    247          1.1  kardel  * The processor load due to the driver is 5.8 percent.
    248          1.1  kardel  */
    249          1.1  kardel #define PDELAY	((.91 + 4.7 - 0.45) / 1000) /* system delay (s) */
    250          1.1  kardel 
    251          1.1  kardel /*
    252          1.1  kardel  * Table of sine values at 4.5-degree increments. This is used by the
    253          1.1  kardel  * synchronous matched filter demodulators.
    254          1.1  kardel  */
    255          1.1  kardel double sintab[] = {
    256          1.1  kardel  0.000000e+00,  7.845910e-02,  1.564345e-01,  2.334454e-01, /* 0-3 */
    257          1.1  kardel  3.090170e-01,  3.826834e-01,  4.539905e-01,  5.224986e-01, /* 4-7 */
    258          1.1  kardel  5.877853e-01,  6.494480e-01,  7.071068e-01,  7.604060e-01, /* 8-11 */
    259          1.1  kardel  8.090170e-01,  8.526402e-01,  8.910065e-01,  9.238795e-01, /* 12-15 */
    260          1.1  kardel  9.510565e-01,  9.723699e-01,  9.876883e-01,  9.969173e-01, /* 16-19 */
    261          1.1  kardel  1.000000e+00,  9.969173e-01,  9.876883e-01,  9.723699e-01, /* 20-23 */
    262          1.1  kardel  9.510565e-01,  9.238795e-01,  8.910065e-01,  8.526402e-01, /* 24-27 */
    263          1.1  kardel  8.090170e-01,  7.604060e-01,  7.071068e-01,  6.494480e-01, /* 28-31 */
    264          1.1  kardel  5.877853e-01,  5.224986e-01,  4.539905e-01,  3.826834e-01, /* 32-35 */
    265          1.1  kardel  3.090170e-01,  2.334454e-01,  1.564345e-01,  7.845910e-02, /* 36-39 */
    266          1.1  kardel -0.000000e+00, -7.845910e-02, -1.564345e-01, -2.334454e-01, /* 40-43 */
    267          1.1  kardel -3.090170e-01, -3.826834e-01, -4.539905e-01, -5.224986e-01, /* 44-47 */
    268          1.1  kardel -5.877853e-01, -6.494480e-01, -7.071068e-01, -7.604060e-01, /* 48-51 */
    269          1.1  kardel -8.090170e-01, -8.526402e-01, -8.910065e-01, -9.238795e-01, /* 52-55 */
    270          1.1  kardel -9.510565e-01, -9.723699e-01, -9.876883e-01, -9.969173e-01, /* 56-59 */
    271          1.1  kardel -1.000000e+00, -9.969173e-01, -9.876883e-01, -9.723699e-01, /* 60-63 */
    272          1.1  kardel -9.510565e-01, -9.238795e-01, -8.910065e-01, -8.526402e-01, /* 64-67 */
    273          1.1  kardel -8.090170e-01, -7.604060e-01, -7.071068e-01, -6.494480e-01, /* 68-71 */
    274          1.1  kardel -5.877853e-01, -5.224986e-01, -4.539905e-01, -3.826834e-01, /* 72-75 */
    275          1.1  kardel -3.090170e-01, -2.334454e-01, -1.564345e-01, -7.845910e-02, /* 76-79 */
    276          1.1  kardel  0.000000e+00};						    /* 80 */
    277          1.1  kardel 
    278          1.1  kardel /*
    279          1.1  kardel  * Decoder operations at the end of each second are driven by a state
    280          1.1  kardel  * machine. The transition matrix consists of a dispatch table indexed
    281          1.1  kardel  * by second number. Each entry in the table contains a case switch
    282          1.1  kardel  * number and argument.
    283          1.1  kardel  */
    284          1.1  kardel struct progx {
    285          1.1  kardel 	int sw;			/* case switch number */
    286          1.1  kardel 	int arg;		/* argument */
    287          1.1  kardel };
    288          1.1  kardel 
    289          1.1  kardel /*
    290          1.1  kardel  * Case switch numbers
    291          1.1  kardel  */
    292          1.1  kardel #define IDLE		0	/* no operation */
    293          1.1  kardel #define COEF		1	/* BCD bit */
    294          1.1  kardel #define COEF1		2	/* BCD bit for minute unit */
    295          1.1  kardel #define COEF2		3	/* BCD bit not used */
    296          1.1  kardel #define DECIM9		4	/* BCD digit 0-9 */
    297          1.1  kardel #define DECIM6		5	/* BCD digit 0-6 */
    298          1.1  kardel #define DECIM3		6	/* BCD digit 0-3 */
    299          1.1  kardel #define DECIM2		7	/* BCD digit 0-2 */
    300          1.1  kardel #define MSCBIT		8	/* miscellaneous bit */
    301          1.1  kardel #define MSC20		9	/* miscellaneous bit */
    302          1.1  kardel #define MSC21		10	/* QSY probe channel */
    303          1.1  kardel #define MIN1		11	/* latch time */
    304          1.1  kardel #define MIN2		12	/* leap second */
    305          1.1  kardel #define SYNC2		13	/* latch minute sync pulse */
    306          1.1  kardel #define SYNC3		14	/* latch data pulse */
    307          1.1  kardel 
    308          1.1  kardel /*
    309          1.1  kardel  * Offsets in decoding matrix
    310          1.1  kardel  */
    311          1.1  kardel #define MN		0	/* minute digits (2) */
    312          1.1  kardel #define HR		2	/* hour digits (2) */
    313          1.1  kardel #define DA		4	/* day digits (3) */
    314          1.1  kardel #define YR		7	/* year digits (2) */
    315          1.1  kardel 
    316          1.1  kardel struct progx progx[] = {
    317          1.1  kardel 	{SYNC2,	0},		/* 0 latch minute sync pulse */
    318          1.1  kardel 	{SYNC3,	0},		/* 1 latch data pulse */
    319          1.1  kardel 	{MSCBIT, DST2},		/* 2 dst2 */
    320          1.1  kardel 	{MSCBIT, SECWAR},	/* 3 lw */
    321          1.1  kardel 	{COEF,	0},		/* 4 1 year units */
    322          1.1  kardel 	{COEF,	1},		/* 5 2 */
    323          1.1  kardel 	{COEF,	2},		/* 6 4 */
    324          1.1  kardel 	{COEF,	3},		/* 7 8 */
    325          1.1  kardel 	{DECIM9, YR},		/* 8 */
    326          1.1  kardel 	{IDLE,	0},		/* 9 p1 */
    327          1.1  kardel 	{COEF1,	0},		/* 10 1 minute units */
    328          1.1  kardel 	{COEF1,	1},		/* 11 2 */
    329          1.1  kardel 	{COEF1,	2},		/* 12 4 */
    330          1.1  kardel 	{COEF1,	3},		/* 13 8 */
    331          1.1  kardel 	{DECIM9, MN},		/* 14 */
    332          1.1  kardel 	{COEF,	0},		/* 15 10 minute tens */
    333          1.1  kardel 	{COEF,	1},		/* 16 20 */
    334          1.1  kardel 	{COEF,	2},		/* 17 40 */
    335          1.1  kardel 	{COEF2,	3},		/* 18 80 (not used) */
    336          1.1  kardel 	{DECIM6, MN + 1},	/* 19 p2 */
    337          1.1  kardel 	{COEF,	0},		/* 20 1 hour units */
    338          1.1  kardel 	{COEF,	1},		/* 21 2 */
    339          1.1  kardel 	{COEF,	2},		/* 22 4 */
    340          1.1  kardel 	{COEF,	3},		/* 23 8 */
    341          1.1  kardel 	{DECIM9, HR},		/* 24 */
    342          1.1  kardel 	{COEF,	0},		/* 25 10 hour tens */
    343          1.1  kardel 	{COEF,	1},		/* 26 20 */
    344          1.1  kardel 	{COEF2,	2},		/* 27 40 (not used) */
    345          1.1  kardel 	{COEF2,	3},		/* 28 80 (not used) */
    346          1.1  kardel 	{DECIM2, HR + 1},	/* 29 p3 */
    347          1.1  kardel 	{COEF,	0},		/* 30 1 day units */
    348          1.1  kardel 	{COEF,	1},		/* 31 2 */
    349          1.1  kardel 	{COEF,	2},		/* 32 4 */
    350          1.1  kardel 	{COEF,	3},		/* 33 8 */
    351          1.1  kardel 	{DECIM9, DA},		/* 34 */
    352          1.1  kardel 	{COEF,	0},		/* 35 10 day tens */
    353          1.1  kardel 	{COEF,	1},		/* 36 20 */
    354          1.1  kardel 	{COEF,	2},		/* 37 40 */
    355          1.1  kardel 	{COEF,	3},		/* 38 80 */
    356          1.1  kardel 	{DECIM9, DA + 1},	/* 39 p4 */
    357          1.1  kardel 	{COEF,	0},		/* 40 100 day hundreds */
    358          1.1  kardel 	{COEF,	1},		/* 41 200 */
    359          1.1  kardel 	{COEF2,	2},		/* 42 400 (not used) */
    360          1.1  kardel 	{COEF2,	3},		/* 43 800 (not used) */
    361          1.1  kardel 	{DECIM3, DA + 2},	/* 44 */
    362          1.1  kardel 	{IDLE,	0},		/* 45 */
    363          1.1  kardel 	{IDLE,	0},		/* 46 */
    364          1.1  kardel 	{IDLE,	0},		/* 47 */
    365          1.1  kardel 	{IDLE,	0},		/* 48 */
    366          1.1  kardel 	{IDLE,	0},		/* 49 p5 */
    367          1.1  kardel 	{MSCBIT, DUTS},		/* 50 dut+- */
    368          1.1  kardel 	{COEF,	0},		/* 51 10 year tens */
    369          1.1  kardel 	{COEF,	1},		/* 52 20 */
    370          1.1  kardel 	{COEF,	2},		/* 53 40 */
    371          1.1  kardel 	{COEF,	3},		/* 54 80 */
    372          1.1  kardel 	{MSC20, DST1},		/* 55 dst1 */
    373          1.1  kardel 	{MSCBIT, DUT1},		/* 56 0.1 dut */
    374          1.1  kardel 	{MSCBIT, DUT2},		/* 57 0.2 */
    375          1.1  kardel 	{MSC21, DUT4},		/* 58 0.4 QSY probe channel */
    376          1.1  kardel 	{MIN1,	0},		/* 59 p6 latch time */
    377          1.1  kardel 	{MIN2,	0}		/* 60 leap second */
    378          1.1  kardel };
    379          1.1  kardel 
    380          1.1  kardel /*
    381          1.1  kardel  * BCD coefficients for maximum-likelihood digit decode
    382          1.1  kardel  */
    383          1.1  kardel #define P15	1.		/* max positive number */
    384          1.1  kardel #define N15	-1.		/* max negative number */
    385          1.1  kardel 
    386          1.1  kardel /*
    387          1.1  kardel  * Digits 0-9
    388          1.1  kardel  */
    389          1.1  kardel #define P9	(P15 / 4)	/* mark (+1) */
    390          1.1  kardel #define N9	(N15 / 4)	/* space (-1) */
    391          1.1  kardel 
    392          1.1  kardel double bcd9[][4] = {
    393          1.1  kardel 	{N9, N9, N9, N9}, 	/* 0 */
    394          1.1  kardel 	{P9, N9, N9, N9}, 	/* 1 */
    395          1.1  kardel 	{N9, P9, N9, N9}, 	/* 2 */
    396          1.1  kardel 	{P9, P9, N9, N9}, 	/* 3 */
    397          1.1  kardel 	{N9, N9, P9, N9}, 	/* 4 */
    398          1.1  kardel 	{P9, N9, P9, N9}, 	/* 5 */
    399          1.1  kardel 	{N9, P9, P9, N9}, 	/* 6 */
    400          1.1  kardel 	{P9, P9, P9, N9}, 	/* 7 */
    401          1.1  kardel 	{N9, N9, N9, P9}, 	/* 8 */
    402          1.1  kardel 	{P9, N9, N9, P9}, 	/* 9 */
    403          1.1  kardel 	{0, 0, 0, 0}		/* backstop */
    404          1.1  kardel };
    405          1.1  kardel 
    406          1.1  kardel /*
    407          1.1  kardel  * Digits 0-6 (minute tens)
    408          1.1  kardel  */
    409          1.1  kardel #define P6	(P15 / 3)	/* mark (+1) */
    410          1.1  kardel #define N6	(N15 / 3)	/* space (-1) */
    411          1.1  kardel 
    412          1.1  kardel double bcd6[][4] = {
    413          1.1  kardel 	{N6, N6, N6, 0}, 	/* 0 */
    414          1.1  kardel 	{P6, N6, N6, 0}, 	/* 1 */
    415          1.1  kardel 	{N6, P6, N6, 0}, 	/* 2 */
    416          1.1  kardel 	{P6, P6, N6, 0}, 	/* 3 */
    417          1.1  kardel 	{N6, N6, P6, 0}, 	/* 4 */
    418          1.1  kardel 	{P6, N6, P6, 0}, 	/* 5 */
    419          1.1  kardel 	{N6, P6, P6, 0}, 	/* 6 */
    420          1.1  kardel 	{0, 0, 0, 0}		/* backstop */
    421          1.1  kardel };
    422          1.1  kardel 
    423          1.1  kardel /*
    424          1.1  kardel  * Digits 0-3 (day hundreds)
    425          1.1  kardel  */
    426          1.1  kardel #define P3	(P15 / 2)	/* mark (+1) */
    427          1.1  kardel #define N3	(N15 / 2)	/* space (-1) */
    428          1.1  kardel 
    429          1.1  kardel double bcd3[][4] = {
    430          1.1  kardel 	{N3, N3, 0, 0}, 	/* 0 */
    431          1.1  kardel 	{P3, N3, 0, 0}, 	/* 1 */
    432          1.1  kardel 	{N3, P3, 0, 0}, 	/* 2 */
    433          1.1  kardel 	{P3, P3, 0, 0}, 	/* 3 */
    434          1.1  kardel 	{0, 0, 0, 0}		/* backstop */
    435          1.1  kardel };
    436          1.1  kardel 
    437          1.1  kardel /*
    438          1.1  kardel  * Digits 0-2 (hour tens)
    439          1.1  kardel  */
    440          1.1  kardel #define P2	(P15 / 2)	/* mark (+1) */
    441          1.1  kardel #define N2	(N15 / 2)	/* space (-1) */
    442          1.1  kardel 
    443          1.1  kardel double bcd2[][4] = {
    444          1.1  kardel 	{N2, N2, 0, 0}, 	/* 0 */
    445          1.1  kardel 	{P2, N2, 0, 0}, 	/* 1 */
    446          1.1  kardel 	{N2, P2, 0, 0}, 	/* 2 */
    447          1.1  kardel 	{0, 0, 0, 0}		/* backstop */
    448          1.1  kardel };
    449          1.1  kardel 
    450          1.1  kardel /*
    451          1.1  kardel  * DST decode (DST2 DST1) for prettyprint
    452          1.1  kardel  */
    453          1.1  kardel char dstcod[] = {
    454          1.1  kardel 	'S',			/* 00 standard time */
    455          1.1  kardel 	'I',			/* 01 set clock ahead at 0200 local */
    456          1.1  kardel 	'O',			/* 10 set clock back at 0200 local */
    457          1.1  kardel 	'D'			/* 11 daylight time */
    458          1.1  kardel };
    459          1.1  kardel 
    460          1.1  kardel /*
    461          1.1  kardel  * The decoding matrix consists of nine row vectors, one for each digit
    462          1.1  kardel  * of the timecode. The digits are stored from least to most significant
    463          1.1  kardel  * order. The maximum-likelihood timecode is formed from the digits
    464          1.1  kardel  * corresponding to the maximum-likelihood values reading in the
    465          1.1  kardel  * opposite order: yy ddd hh:mm.
    466          1.1  kardel  */
    467          1.1  kardel struct decvec {
    468          1.1  kardel 	int radix;		/* radix (3, 4, 6, 10) */
    469          1.1  kardel 	int digit;		/* current clock digit */
    470          1.1  kardel 	int count;		/* match count */
    471          1.1  kardel 	double digprb;		/* max digit probability */
    472          1.1  kardel 	double digsnr;		/* likelihood function (dB) */
    473          1.1  kardel 	double like[10];	/* likelihood integrator 0-9 */
    474          1.1  kardel };
    475          1.1  kardel 
    476          1.1  kardel /*
    477          1.1  kardel  * The station structure (sp) is used to acquire the minute pulse from
    478          1.1  kardel  * WWV and/or WWVH. These stations are distinguished by the frequency
    479          1.1  kardel  * used for the second and minute sync pulses, 1000 Hz for WWV and 1200
    480          1.1  kardel  * Hz for WWVH. Other than frequency, the format is the same.
    481          1.1  kardel  */
    482          1.1  kardel struct sync {
    483          1.1  kardel 	double	epoch;		/* accumulated epoch differences */
    484          1.1  kardel 	double	maxeng;		/* sync max energy */
    485          1.1  kardel 	double	noieng;		/* sync noise energy */
    486          1.1  kardel 	long	pos;		/* max amplitude position */
    487          1.1  kardel 	long	lastpos;	/* last max position */
    488          1.1  kardel 	long	mepoch;		/* minute synch epoch */
    489          1.1  kardel 
    490          1.1  kardel 	double	amp;		/* sync signal */
    491          1.1  kardel 	double	syneng;		/* sync signal max */
    492          1.1  kardel 	double	synmax;		/* sync signal max latched at 0 s */
    493          1.1  kardel 	double	synsnr;		/* sync signal SNR */
    494          1.1  kardel 	double	metric;		/* signal quality metric */
    495          1.1  kardel 	int	reach;		/* reachability register */
    496          1.1  kardel 	int	count;		/* bit counter */
    497          1.1  kardel 	int	select;		/* select bits */
    498          1.1  kardel 	char	refid[5];	/* reference identifier */
    499          1.1  kardel };
    500          1.1  kardel 
    501          1.1  kardel /*
    502          1.1  kardel  * The channel structure (cp) is used to mitigate between channels.
    503          1.1  kardel  */
    504          1.1  kardel struct chan {
    505          1.1  kardel 	int	gain;		/* audio gain */
    506          1.1  kardel 	struct sync wwv;	/* wwv station */
    507          1.1  kardel 	struct sync wwvh;	/* wwvh station */
    508          1.1  kardel };
    509          1.1  kardel 
    510          1.1  kardel /*
    511          1.1  kardel  * WWV unit control structure (up)
    512          1.1  kardel  */
    513          1.1  kardel struct wwvunit {
    514          1.1  kardel 	l_fp	timestamp;	/* audio sample timestamp */
    515          1.1  kardel 	l_fp	tick;		/* audio sample increment */
    516          1.1  kardel 	double	phase, freq;	/* logical clock phase and frequency */
    517          1.1  kardel 	double	monitor;	/* audio monitor point */
    518          1.1  kardel 	double	pdelay;		/* propagation delay (s) */
    519          1.1  kardel #ifdef ICOM
    520          1.1  kardel 	int	fd_icom;	/* ICOM file descriptor */
    521          1.1  kardel #endif /* ICOM */
    522          1.1  kardel 	int	errflg;		/* error flags */
    523          1.1  kardel 	int	watch;		/* watchcat */
    524          1.1  kardel 
    525          1.1  kardel 	/*
    526          1.1  kardel 	 * Audio codec variables
    527          1.1  kardel 	 */
    528          1.1  kardel 	double	comp[SIZE];	/* decompanding table */
    529          1.1  kardel  	int	port;		/* codec port */
    530          1.1  kardel 	int	gain;		/* codec gain */
    531          1.1  kardel 	int	mongain;	/* codec monitor gain */
    532          1.1  kardel 	int	clipcnt;	/* sample clipped count */
    533          1.1  kardel 
    534          1.1  kardel 	/*
    535          1.1  kardel 	 * Variables used to establish basic system timing
    536          1.1  kardel 	 */
    537          1.1  kardel 	int	avgint;		/* master time constant */
    538          1.1  kardel 	int	yepoch;		/* sync epoch */
    539          1.1  kardel 	int	repoch;		/* buffered sync epoch */
    540          1.1  kardel 	double	epomax;		/* second sync amplitude */
    541          1.1  kardel 	double	eposnr;		/* second sync SNR */
    542          1.1  kardel 	double	irig;		/* data I channel amplitude */
    543          1.1  kardel 	double	qrig;		/* data Q channel amplitude */
    544          1.1  kardel 	int	datapt;		/* 100 Hz ramp */
    545          1.1  kardel 	double	datpha;		/* 100 Hz VFO control */
    546          1.1  kardel 	int	rphase;		/* second sample counter */
    547          1.1  kardel 	long	mphase;		/* minute sample counter */
    548          1.1  kardel 
    549          1.1  kardel 	/*
    550          1.1  kardel 	 * Variables used to mitigate which channel to use
    551          1.1  kardel 	 */
    552          1.1  kardel 	struct chan mitig[NCHAN]; /* channel data */
    553          1.1  kardel 	struct sync *sptr;	/* station pointer */
    554          1.1  kardel 	int	dchan;		/* data channel */
    555          1.1  kardel 	int	schan;		/* probe channel */
    556          1.1  kardel 	int	achan;		/* active channel */
    557          1.1  kardel 
    558          1.1  kardel 	/*
    559          1.1  kardel 	 * Variables used by the clock state machine
    560          1.1  kardel 	 */
    561          1.1  kardel 	struct decvec decvec[9]; /* decoding matrix */
    562          1.1  kardel 	int	rsec;		/* seconds counter */
    563          1.1  kardel 	int	digcnt;		/* count of digits synchronized */
    564          1.1  kardel 
    565          1.1  kardel 	/*
    566          1.1  kardel 	 * Variables used to estimate signal levels and bit/digit
    567          1.1  kardel 	 * probabilities
    568          1.1  kardel 	 */
    569          1.1  kardel 	double	datsig;		/* data signal max */
    570          1.1  kardel 	double	datsnr;		/* data signal SNR (dB) */
    571          1.1  kardel 
    572          1.1  kardel 	/*
    573          1.1  kardel 	 * Variables used to establish status and alarm conditions
    574          1.1  kardel 	 */
    575          1.1  kardel 	int	status;		/* status bits */
    576          1.1  kardel 	int	alarm;		/* alarm flashers */
    577          1.1  kardel 	int	misc;		/* miscellaneous timecode bits */
    578          1.1  kardel 	int	errcnt;		/* data bit error counter */
    579          1.1  kardel };
    580          1.1  kardel 
    581          1.1  kardel /*
    582          1.1  kardel  * Function prototypes
    583          1.1  kardel  */
    584          1.1  kardel static	int	wwv_start	(int, struct peer *);
    585          1.1  kardel static	void	wwv_shutdown	(int, struct peer *);
    586          1.1  kardel static	void	wwv_receive	(struct recvbuf *);
    587          1.1  kardel static	void	wwv_poll	(int, struct peer *);
    588          1.1  kardel 
    589          1.1  kardel /*
    590          1.1  kardel  * More function prototypes
    591          1.1  kardel  */
    592          1.1  kardel static	void	wwv_epoch	(struct peer *);
    593          1.1  kardel static	void	wwv_rf		(struct peer *, double);
    594          1.1  kardel static	void	wwv_endpoc	(struct peer *, int);
    595          1.1  kardel static	void	wwv_rsec	(struct peer *, double);
    596          1.1  kardel static	void	wwv_qrz		(struct peer *, struct sync *, int);
    597          1.1  kardel static	void	wwv_corr4	(struct peer *, struct decvec *,
    598          1.1  kardel 				    double [], double [][4]);
    599          1.1  kardel static	void	wwv_gain	(struct peer *);
    600          1.1  kardel static	void	wwv_tsec	(struct peer *);
    601  1.1.1.1.6.1    yamt static	int	timecode	(struct wwvunit *, char *, size_t);
    602          1.1  kardel static	double	wwv_snr		(double, double);
    603          1.1  kardel static	int	carry		(struct decvec *);
    604          1.1  kardel static	int	wwv_newchan	(struct peer *);
    605          1.1  kardel static	void	wwv_newgame	(struct peer *);
    606          1.1  kardel static	double	wwv_metric	(struct sync *);
    607          1.1  kardel static	void	wwv_clock	(struct peer *);
    608          1.1  kardel #ifdef ICOM
    609          1.1  kardel static	int	wwv_qsy		(struct peer *, int);
    610          1.1  kardel #endif /* ICOM */
    611          1.1  kardel 
    612          1.1  kardel static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) */
    613          1.1  kardel 
    614          1.1  kardel /*
    615          1.1  kardel  * Transfer vector
    616          1.1  kardel  */
    617          1.1  kardel struct	refclock refclock_wwv = {
    618          1.1  kardel 	wwv_start,		/* start up driver */
    619          1.1  kardel 	wwv_shutdown,		/* shut down driver */
    620          1.1  kardel 	wwv_poll,		/* transmit poll message */
    621          1.1  kardel 	noentry,		/* not used (old wwv_control) */
    622          1.1  kardel 	noentry,		/* initialize driver (not used) */
    623          1.1  kardel 	noentry,		/* not used (old wwv_buginfo) */
    624          1.1  kardel 	NOFLAGS			/* not used */
    625          1.1  kardel };
    626          1.1  kardel 
    627          1.1  kardel 
    628          1.1  kardel /*
    629          1.1  kardel  * wwv_start - open the devices and initialize data for processing
    630          1.1  kardel  */
    631          1.1  kardel static int
    632          1.1  kardel wwv_start(
    633          1.1  kardel 	int	unit,		/* instance number (used by PCM) */
    634          1.1  kardel 	struct peer *peer	/* peer structure pointer */
    635          1.1  kardel 	)
    636          1.1  kardel {
    637          1.1  kardel 	struct refclockproc *pp;
    638          1.1  kardel 	struct wwvunit *up;
    639          1.1  kardel #ifdef ICOM
    640          1.1  kardel 	int	temp;
    641          1.1  kardel #endif /* ICOM */
    642          1.1  kardel 
    643          1.1  kardel 	/*
    644          1.1  kardel 	 * Local variables
    645          1.1  kardel 	 */
    646          1.1  kardel 	int	fd;		/* file descriptor */
    647          1.1  kardel 	int	i;		/* index */
    648          1.1  kardel 	double	step;		/* codec adjustment */
    649          1.1  kardel 
    650          1.1  kardel 	/*
    651          1.1  kardel 	 * Open audio device
    652          1.1  kardel 	 */
    653          1.1  kardel 	fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
    654          1.1  kardel 	if (fd < 0)
    655          1.1  kardel 		return (0);
    656          1.1  kardel #ifdef DEBUG
    657          1.1  kardel 	if (debug)
    658          1.1  kardel 		audio_show();
    659          1.1  kardel #endif /* DEBUG */
    660          1.1  kardel 
    661          1.1  kardel 	/*
    662          1.1  kardel 	 * Allocate and initialize unit structure
    663          1.1  kardel 	 */
    664  1.1.1.1.6.1    yamt 	up = emalloc_zero(sizeof(*up));
    665          1.1  kardel 	pp = peer->procptr;
    666          1.1  kardel 	pp->io.clock_recv = wwv_receive;
    667  1.1.1.1.6.1    yamt 	pp->io.srcclock = peer;
    668          1.1  kardel 	pp->io.datalen = 0;
    669          1.1  kardel 	pp->io.fd = fd;
    670          1.1  kardel 	if (!io_addclock(&pp->io)) {
    671          1.1  kardel 		close(fd);
    672          1.1  kardel 		free(up);
    673          1.1  kardel 		return (0);
    674          1.1  kardel 	}
    675  1.1.1.1.6.1    yamt 	pp->unitptr = up;
    676          1.1  kardel 
    677          1.1  kardel 	/*
    678          1.1  kardel 	 * Initialize miscellaneous variables
    679          1.1  kardel 	 */
    680          1.1  kardel 	peer->precision = PRECISION;
    681          1.1  kardel 	pp->clockdesc = DESCRIPTION;
    682          1.1  kardel 
    683          1.1  kardel 	/*
    684          1.1  kardel 	 * The companded samples are encoded sign-magnitude. The table
    685          1.1  kardel 	 * contains all the 256 values in the interest of speed.
    686          1.1  kardel 	 */
    687          1.1  kardel 	up->comp[0] = up->comp[OFFSET] = 0.;
    688          1.1  kardel 	up->comp[1] = 1.; up->comp[OFFSET + 1] = -1.;
    689          1.1  kardel 	up->comp[2] = 3.; up->comp[OFFSET + 2] = -3.;
    690          1.1  kardel 	step = 2.;
    691          1.1  kardel 	for (i = 3; i < OFFSET; i++) {
    692          1.1  kardel 		up->comp[i] = up->comp[i - 1] + step;
    693          1.1  kardel 		up->comp[OFFSET + i] = -up->comp[i];
    694  1.1.1.1.6.1    yamt 		if (i % 16 == 0)
    695  1.1.1.1.6.1    yamt 			step *= 2.;
    696          1.1  kardel 	}
    697  1.1.1.1.6.1    yamt 	DTOLFP(1. / WWV_SEC, &up->tick);
    698          1.1  kardel 
    699          1.1  kardel 	/*
    700          1.1  kardel 	 * Initialize the decoding matrix with the radix for each digit
    701          1.1  kardel 	 * position.
    702          1.1  kardel 	 */
    703          1.1  kardel 	up->decvec[MN].radix = 10;	/* minutes */
    704          1.1  kardel 	up->decvec[MN + 1].radix = 6;
    705          1.1  kardel 	up->decvec[HR].radix = 10;	/* hours */
    706          1.1  kardel 	up->decvec[HR + 1].radix = 3;
    707          1.1  kardel 	up->decvec[DA].radix = 10;	/* days */
    708          1.1  kardel 	up->decvec[DA + 1].radix = 10;
    709          1.1  kardel 	up->decvec[DA + 2].radix = 4;
    710          1.1  kardel 	up->decvec[YR].radix = 10;	/* years */
    711          1.1  kardel 	up->decvec[YR + 1].radix = 10;
    712          1.1  kardel 
    713          1.1  kardel #ifdef ICOM
    714          1.1  kardel 	/*
    715          1.1  kardel 	 * Initialize autotune if available. Note that the ICOM select
    716          1.1  kardel 	 * code must be less than 128, so the high order bit can be used
    717          1.1  kardel 	 * to select the line speed 0 (9600 bps) or 1 (1200 bps). Note
    718          1.1  kardel 	 * we don't complain if the ICOM device is not there; but, if it
    719          1.1  kardel 	 * is, the radio better be working.
    720          1.1  kardel 	 */
    721          1.1  kardel 	temp = 0;
    722          1.1  kardel #ifdef DEBUG
    723          1.1  kardel 	if (debug > 1)
    724          1.1  kardel 		temp = P_TRACE;
    725          1.1  kardel #endif /* DEBUG */
    726          1.1  kardel 	if (peer->ttl != 0) {
    727          1.1  kardel 		if (peer->ttl & 0x80)
    728          1.1  kardel 			up->fd_icom = icom_init("/dev/icom", B1200,
    729          1.1  kardel 			    temp);
    730          1.1  kardel 		else
    731          1.1  kardel 			up->fd_icom = icom_init("/dev/icom", B9600,
    732          1.1  kardel 			    temp);
    733          1.1  kardel 	}
    734          1.1  kardel 	if (up->fd_icom > 0) {
    735          1.1  kardel 		if (wwv_qsy(peer, DCHAN) != 0) {
    736          1.1  kardel 			msyslog(LOG_NOTICE, "icom: radio not found");
    737          1.1  kardel 			close(up->fd_icom);
    738          1.1  kardel 			up->fd_icom = 0;
    739          1.1  kardel 		} else {
    740          1.1  kardel 			msyslog(LOG_NOTICE, "icom: autotune enabled");
    741          1.1  kardel 		}
    742          1.1  kardel 	}
    743          1.1  kardel #endif /* ICOM */
    744          1.1  kardel 
    745          1.1  kardel 	/*
    746          1.1  kardel 	 * Let the games begin.
    747          1.1  kardel 	 */
    748          1.1  kardel 	wwv_newgame(peer);
    749          1.1  kardel 	return (1);
    750          1.1  kardel }
    751          1.1  kardel 
    752          1.1  kardel 
    753          1.1  kardel /*
    754          1.1  kardel  * wwv_shutdown - shut down the clock
    755          1.1  kardel  */
    756          1.1  kardel static void
    757          1.1  kardel wwv_shutdown(
    758          1.1  kardel 	int	unit,		/* instance number (not used) */
    759          1.1  kardel 	struct peer *peer	/* peer structure pointer */
    760          1.1  kardel 	)
    761          1.1  kardel {
    762          1.1  kardel 	struct refclockproc *pp;
    763          1.1  kardel 	struct wwvunit *up;
    764          1.1  kardel 
    765          1.1  kardel 	pp = peer->procptr;
    766  1.1.1.1.6.1    yamt 	up = pp->unitptr;
    767          1.1  kardel 	if (up == NULL)
    768          1.1  kardel 		return;
    769          1.1  kardel 
    770          1.1  kardel 	io_closeclock(&pp->io);
    771          1.1  kardel #ifdef ICOM
    772          1.1  kardel 	if (up->fd_icom > 0)
    773          1.1  kardel 		close(up->fd_icom);
    774          1.1  kardel #endif /* ICOM */
    775          1.1  kardel 	free(up);
    776          1.1  kardel }
    777          1.1  kardel 
    778          1.1  kardel 
    779          1.1  kardel /*
    780          1.1  kardel  * wwv_receive - receive data from the audio device
    781          1.1  kardel  *
    782          1.1  kardel  * This routine reads input samples and adjusts the logical clock to
    783          1.1  kardel  * track the A/D sample clock by dropping or duplicating codec samples.
    784          1.1  kardel  * It also controls the A/D signal level with an AGC loop to mimimize
    785          1.1  kardel  * quantization noise and avoid overload.
    786          1.1  kardel  */
    787          1.1  kardel static void
    788          1.1  kardel wwv_receive(
    789          1.1  kardel 	struct recvbuf *rbufp	/* receive buffer structure pointer */
    790          1.1  kardel 	)
    791          1.1  kardel {
    792          1.1  kardel 	struct peer *peer;
    793          1.1  kardel 	struct refclockproc *pp;
    794          1.1  kardel 	struct wwvunit *up;
    795          1.1  kardel 
    796          1.1  kardel 	/*
    797          1.1  kardel 	 * Local variables
    798          1.1  kardel 	 */
    799          1.1  kardel 	double	sample;		/* codec sample */
    800          1.1  kardel 	u_char	*dpt;		/* buffer pointer */
    801          1.1  kardel 	int	bufcnt;		/* buffer counter */
    802          1.1  kardel 	l_fp	ltemp;
    803          1.1  kardel 
    804  1.1.1.1.6.1    yamt 	peer = rbufp->recv_peer;
    805          1.1  kardel 	pp = peer->procptr;
    806  1.1.1.1.6.1    yamt 	up = pp->unitptr;
    807          1.1  kardel 
    808          1.1  kardel 	/*
    809          1.1  kardel 	 * Main loop - read until there ain't no more. Note codec
    810          1.1  kardel 	 * samples are bit-inverted.
    811          1.1  kardel 	 */
    812  1.1.1.1.6.1    yamt 	DTOLFP((double)rbufp->recv_length / WWV_SEC, &ltemp);
    813          1.1  kardel 	L_SUB(&rbufp->recv_time, &ltemp);
    814          1.1  kardel 	up->timestamp = rbufp->recv_time;
    815          1.1  kardel 	dpt = rbufp->recv_buffer;
    816          1.1  kardel 	for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
    817          1.1  kardel 		sample = up->comp[~*dpt++ & 0xff];
    818          1.1  kardel 
    819          1.1  kardel 		/*
    820          1.1  kardel 		 * Clip noise spikes greater than MAXAMP (6000) and
    821          1.1  kardel 		 * record the number of clips to be used later by the
    822          1.1  kardel 		 * AGC.
    823          1.1  kardel 		 */
    824          1.1  kardel 		if (sample > MAXAMP) {
    825          1.1  kardel 			sample = MAXAMP;
    826          1.1  kardel 			up->clipcnt++;
    827          1.1  kardel 		} else if (sample < -MAXAMP) {
    828          1.1  kardel 			sample = -MAXAMP;
    829          1.1  kardel 			up->clipcnt++;
    830          1.1  kardel 		}
    831          1.1  kardel 
    832          1.1  kardel 		/*
    833          1.1  kardel 		 * Variable frequency oscillator. The codec oscillator
    834          1.1  kardel 		 * runs at the nominal rate of 8000 samples per second,
    835          1.1  kardel 		 * or 125 us per sample. A frequency change of one unit
    836          1.1  kardel 		 * results in either duplicating or deleting one sample
    837          1.1  kardel 		 * per second, which results in a frequency change of
    838          1.1  kardel 		 * 125 PPM.
    839          1.1  kardel 		 */
    840  1.1.1.1.6.1    yamt 		up->phase += (up->freq + clock_codec) / WWV_SEC;
    841          1.1  kardel 		if (up->phase >= .5) {
    842          1.1  kardel 			up->phase -= 1.;
    843          1.1  kardel 		} else if (up->phase < -.5) {
    844          1.1  kardel 			up->phase += 1.;
    845          1.1  kardel 			wwv_rf(peer, sample);
    846          1.1  kardel 			wwv_rf(peer, sample);
    847          1.1  kardel 		} else {
    848          1.1  kardel 			wwv_rf(peer, sample);
    849          1.1  kardel 		}
    850          1.1  kardel 		L_ADD(&up->timestamp, &up->tick);
    851          1.1  kardel 	}
    852          1.1  kardel 
    853          1.1  kardel 	/*
    854          1.1  kardel 	 * Set the input port and monitor gain for the next buffer.
    855          1.1  kardel 	 */
    856          1.1  kardel 	if (pp->sloppyclockflag & CLK_FLAG2)
    857          1.1  kardel 		up->port = 2;
    858          1.1  kardel 	else
    859          1.1  kardel 		up->port = 1;
    860          1.1  kardel 	if (pp->sloppyclockflag & CLK_FLAG3)
    861          1.1  kardel 		up->mongain = MONGAIN;
    862          1.1  kardel 	else
    863          1.1  kardel 		up->mongain = 0;
    864          1.1  kardel }
    865          1.1  kardel 
    866          1.1  kardel 
    867          1.1  kardel /*
    868          1.1  kardel  * wwv_poll - called by the transmit procedure
    869          1.1  kardel  *
    870          1.1  kardel  * This routine keeps track of status. If no offset samples have been
    871          1.1  kardel  * processed during a poll interval, a timeout event is declared. If
    872          1.1  kardel  * errors have have occurred during the interval, they are reported as
    873          1.1  kardel  * well.
    874          1.1  kardel  */
    875          1.1  kardel static void
    876          1.1  kardel wwv_poll(
    877          1.1  kardel 	int	unit,		/* instance number (not used) */
    878          1.1  kardel 	struct peer *peer	/* peer structure pointer */
    879          1.1  kardel 	)
    880          1.1  kardel {
    881          1.1  kardel 	struct refclockproc *pp;
    882          1.1  kardel 	struct wwvunit *up;
    883          1.1  kardel 
    884          1.1  kardel 	pp = peer->procptr;
    885  1.1.1.1.6.1    yamt 	up = pp->unitptr;
    886          1.1  kardel 	if (up->errflg)
    887          1.1  kardel 		refclock_report(peer, up->errflg);
    888          1.1  kardel 	up->errflg = 0;
    889          1.1  kardel 	pp->polls++;
    890          1.1  kardel }
    891          1.1  kardel 
    892          1.1  kardel 
    893          1.1  kardel /*
    894          1.1  kardel  * wwv_rf - process signals and demodulate to baseband
    895          1.1  kardel  *
    896          1.1  kardel  * This routine grooms and filters decompanded raw audio samples. The
    897          1.1  kardel  * output signal is the 100-Hz filtered baseband data signal in
    898          1.1  kardel  * quadrature phase. The routine also determines the minute synch epoch,
    899          1.1  kardel  * as well as certain signal maxima, minima and related values.
    900          1.1  kardel  *
    901          1.1  kardel  * There are two 1-s ramps used by this program. Both count the 8000
    902          1.1  kardel  * logical clock samples spanning exactly one second. The epoch ramp
    903          1.1  kardel  * counts the samples starting at an arbitrary time. The rphase ramp
    904          1.1  kardel  * counts the samples starting at the 5-ms second sync pulse found
    905          1.1  kardel  * during the epoch ramp.
    906          1.1  kardel  *
    907          1.1  kardel  * There are two 1-m ramps used by this program. The mphase ramp counts
    908          1.1  kardel  * the 480,000 logical clock samples spanning exactly one minute and
    909          1.1  kardel  * starting at an arbitrary time. The rsec ramp counts the 60 seconds of
    910          1.1  kardel  * the minute starting at the 800-ms minute sync pulse found during the
    911          1.1  kardel  * mphase ramp. The rsec ramp drives the seconds state machine to
    912          1.1  kardel  * determine the bits and digits of the timecode.
    913          1.1  kardel  *
    914          1.1  kardel  * Demodulation operations are based on three synthesized quadrature
    915          1.1  kardel  * sinusoids: 100 Hz for the data signal, 1000 Hz for the WWV sync
    916          1.1  kardel  * signal and 1200 Hz for the WWVH sync signal. These drive synchronous
    917          1.1  kardel  * matched filters for the data signal (170 ms at 100 Hz), WWV minute
    918          1.1  kardel  * sync signal (800 ms at 1000 Hz) and WWVH minute sync signal (800 ms
    919          1.1  kardel  * at 1200 Hz). Two additional matched filters are switched in
    920          1.1  kardel  * as required for the WWV second sync signal (5 cycles at 1000 Hz) and
    921          1.1  kardel  * WWVH second sync signal (6 cycles at 1200 Hz).
    922          1.1  kardel  */
    923          1.1  kardel static void
    924          1.1  kardel wwv_rf(
    925          1.1  kardel 	struct peer *peer,	/* peerstructure pointer */
    926          1.1  kardel 	double isig		/* input signal */
    927          1.1  kardel 	)
    928          1.1  kardel {
    929          1.1  kardel 	struct refclockproc *pp;
    930          1.1  kardel 	struct wwvunit *up;
    931          1.1  kardel 	struct sync *sp, *rp;
    932          1.1  kardel 
    933          1.1  kardel 	static double lpf[5];	/* 150-Hz lpf delay line */
    934          1.1  kardel 	double data;		/* lpf output */
    935          1.1  kardel 	static double bpf[9];	/* 1000/1200-Hz bpf delay line */
    936          1.1  kardel 	double syncx;		/* bpf output */
    937          1.1  kardel 	static double mf[41];	/* 1000/1200-Hz mf delay line */
    938          1.1  kardel 	double mfsync;		/* mf output */
    939          1.1  kardel 
    940          1.1  kardel 	static int iptr;	/* data channel pointer */
    941          1.1  kardel 	static double ibuf[DATSIZ]; /* data I channel delay line */
    942          1.1  kardel 	static double qbuf[DATSIZ]; /* data Q channel delay line */
    943          1.1  kardel 
    944          1.1  kardel 	static int jptr;	/* sync channel pointer */
    945          1.1  kardel 	static int kptr;	/* tick channel pointer */
    946          1.1  kardel 
    947          1.1  kardel 	static int csinptr;	/* wwv channel phase */
    948          1.1  kardel 	static double cibuf[SYNSIZ]; /* wwv I channel delay line */
    949          1.1  kardel 	static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */
    950          1.1  kardel 	static double ciamp;	/* wwv I channel amplitude */
    951          1.1  kardel 	static double cqamp;	/* wwv Q channel amplitude */
    952          1.1  kardel 
    953          1.1  kardel 	static double csibuf[TCKSIZ]; /* wwv I tick delay line */
    954          1.1  kardel 	static double csqbuf[TCKSIZ]; /* wwv Q tick delay line */
    955          1.1  kardel 	static double csiamp;	/* wwv I tick amplitude */
    956          1.1  kardel 	static double csqamp;	/* wwv Q tick amplitude */
    957          1.1  kardel 
    958          1.1  kardel 	static int hsinptr;	/* wwvh channel phase */
    959          1.1  kardel 	static double hibuf[SYNSIZ]; /* wwvh I channel delay line */
    960          1.1  kardel 	static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */
    961          1.1  kardel 	static double hiamp;	/* wwvh I channel amplitude */
    962          1.1  kardel 	static double hqamp;	/* wwvh Q channel amplitude */
    963          1.1  kardel 
    964          1.1  kardel 	static double hsibuf[TCKSIZ]; /* wwvh I tick delay line */
    965          1.1  kardel 	static double hsqbuf[TCKSIZ]; /* wwvh Q tick delay line */
    966          1.1  kardel 	static double hsiamp;	/* wwvh I tick amplitude */
    967          1.1  kardel 	static double hsqamp;	/* wwvh Q tick amplitude */
    968          1.1  kardel 
    969  1.1.1.1.6.1    yamt 	static double epobuf[WWV_SEC]; /* second sync comb filter */
    970          1.1  kardel 	static double epomax, nxtmax; /* second sync amplitude buffer */
    971          1.1  kardel 	static int epopos;	/* epoch second sync position buffer */
    972          1.1  kardel 
    973          1.1  kardel 	static int iniflg;	/* initialization flag */
    974          1.1  kardel 	int	epoch;		/* comb filter index */
    975          1.1  kardel 	double	dtemp;
    976          1.1  kardel 	int	i;
    977          1.1  kardel 
    978          1.1  kardel 	pp = peer->procptr;
    979  1.1.1.1.6.1    yamt 	up = pp->unitptr;
    980          1.1  kardel 
    981          1.1  kardel 	if (!iniflg) {
    982          1.1  kardel 		iniflg = 1;
    983          1.1  kardel 		memset((char *)lpf, 0, sizeof(lpf));
    984          1.1  kardel 		memset((char *)bpf, 0, sizeof(bpf));
    985          1.1  kardel 		memset((char *)mf, 0, sizeof(mf));
    986          1.1  kardel 		memset((char *)ibuf, 0, sizeof(ibuf));
    987          1.1  kardel 		memset((char *)qbuf, 0, sizeof(qbuf));
    988          1.1  kardel 		memset((char *)cibuf, 0, sizeof(cibuf));
    989          1.1  kardel 		memset((char *)cqbuf, 0, sizeof(cqbuf));
    990          1.1  kardel 		memset((char *)csibuf, 0, sizeof(csibuf));
    991          1.1  kardel 		memset((char *)csqbuf, 0, sizeof(csqbuf));
    992          1.1  kardel 		memset((char *)hibuf, 0, sizeof(hibuf));
    993          1.1  kardel 		memset((char *)hqbuf, 0, sizeof(hqbuf));
    994          1.1  kardel 		memset((char *)hsibuf, 0, sizeof(hsibuf));
    995          1.1  kardel 		memset((char *)hsqbuf, 0, sizeof(hsqbuf));
    996          1.1  kardel 		memset((char *)epobuf, 0, sizeof(epobuf));
    997          1.1  kardel 	}
    998          1.1  kardel 
    999          1.1  kardel 	/*
   1000          1.1  kardel 	 * Baseband data demodulation. The 100-Hz subcarrier is
   1001          1.1  kardel 	 * extracted using a 150-Hz IIR lowpass filter. This attenuates
   1002          1.1  kardel 	 * the 1000/1200-Hz sync signals, as well as the 440-Hz and
   1003          1.1  kardel 	 * 600-Hz tones and most of the noise and voice modulation
   1004          1.1  kardel 	 * components.
   1005          1.1  kardel 	 *
   1006          1.1  kardel 	 * The subcarrier is transmitted 10 dB down from the carrier.
   1007          1.1  kardel 	 * The DGAIN parameter can be adjusted for this and to
   1008          1.1  kardel 	 * compensate for the radio audio response at 100 Hz.
   1009          1.1  kardel 	 *
   1010          1.1  kardel 	 * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
   1011          1.1  kardel 	 * passband ripple, -50 dB stopband ripple, phase delay 0.97 ms.
   1012          1.1  kardel 	 */
   1013          1.1  kardel 	data = (lpf[4] = lpf[3]) * 8.360961e-01;
   1014          1.1  kardel 	data += (lpf[3] = lpf[2]) * -3.481740e+00;
   1015          1.1  kardel 	data += (lpf[2] = lpf[1]) * 5.452988e+00;
   1016          1.1  kardel 	data += (lpf[1] = lpf[0]) * -3.807229e+00;
   1017          1.1  kardel 	lpf[0] = isig * DGAIN - data;
   1018          1.1  kardel 	data = lpf[0] * 3.281435e-03
   1019          1.1  kardel 	    + lpf[1] * -1.149947e-02
   1020          1.1  kardel 	    + lpf[2] * 1.654858e-02
   1021          1.1  kardel 	    + lpf[3] * -1.149947e-02
   1022          1.1  kardel 	    + lpf[4] * 3.281435e-03;
   1023          1.1  kardel 
   1024          1.1  kardel 	/*
   1025          1.1  kardel 	 * The 100-Hz data signal is demodulated using a pair of
   1026          1.1  kardel 	 * quadrature multipliers, matched filters and a phase lock
   1027          1.1  kardel 	 * loop. The I and Q quadrature data signals are produced by
   1028          1.1  kardel 	 * multiplying the filtered signal by 100-Hz sine and cosine
   1029          1.1  kardel 	 * signals, respectively. The signals are processed by 170-ms
   1030          1.1  kardel 	 * synchronous matched filters to produce the amplitude and
   1031          1.1  kardel 	 * phase signals used by the demodulator. The signals are scaled
   1032          1.1  kardel 	 * to produce unit energy at the maximum value.
   1033          1.1  kardel 	 */
   1034          1.1  kardel 	i = up->datapt;
   1035          1.1  kardel 	up->datapt = (up->datapt + IN100) % 80;
   1036          1.1  kardel 	dtemp = sintab[i] * data / (MS / 2. * DATCYC);
   1037          1.1  kardel 	up->irig -= ibuf[iptr];
   1038          1.1  kardel 	ibuf[iptr] = dtemp;
   1039          1.1  kardel 	up->irig += dtemp;
   1040          1.1  kardel 
   1041          1.1  kardel 	i = (i + 20) % 80;
   1042          1.1  kardel 	dtemp = sintab[i] * data / (MS / 2. * DATCYC);
   1043          1.1  kardel 	up->qrig -= qbuf[iptr];
   1044          1.1  kardel 	qbuf[iptr] = dtemp;
   1045          1.1  kardel 	up->qrig += dtemp;
   1046          1.1  kardel 	iptr = (iptr + 1) % DATSIZ;
   1047          1.1  kardel 
   1048          1.1  kardel 	/*
   1049          1.1  kardel 	 * Baseband sync demodulation. The 1000/1200 sync signals are
   1050          1.1  kardel 	 * extracted using a 600-Hz IIR bandpass filter. This removes
   1051          1.1  kardel 	 * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz
   1052          1.1  kardel 	 * tones and most of the noise and voice modulation components.
   1053          1.1  kardel 	 *
   1054          1.1  kardel 	 * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
   1055          1.1  kardel 	 * passband ripple, -50 dB stopband ripple, phase delay 0.91 ms.
   1056          1.1  kardel 	 */
   1057          1.1  kardel 	syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
   1058          1.1  kardel 	syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
   1059          1.1  kardel 	syncx += (bpf[6] = bpf[5]) * 8.110921e+00;
   1060          1.1  kardel 	syncx += (bpf[5] = bpf[4]) * -1.517732e+01;
   1061          1.1  kardel 	syncx += (bpf[4] = bpf[3]) * 1.975197e+01;
   1062          1.1  kardel 	syncx += (bpf[3] = bpf[2]) * -1.814365e+01;
   1063          1.1  kardel 	syncx += (bpf[2] = bpf[1]) * 1.159783e+01;
   1064          1.1  kardel 	syncx += (bpf[1] = bpf[0]) * -4.735040e+00;
   1065          1.1  kardel 	bpf[0] = isig - syncx;
   1066          1.1  kardel 	syncx = bpf[0] * 8.203628e-03
   1067          1.1  kardel 	    + bpf[1] * -2.375732e-02
   1068          1.1  kardel 	    + bpf[2] * 3.353214e-02
   1069          1.1  kardel 	    + bpf[3] * -4.080258e-02
   1070          1.1  kardel 	    + bpf[4] * 4.605479e-02
   1071          1.1  kardel 	    + bpf[5] * -4.080258e-02
   1072          1.1  kardel 	    + bpf[6] * 3.353214e-02
   1073          1.1  kardel 	    + bpf[7] * -2.375732e-02
   1074          1.1  kardel 	    + bpf[8] * 8.203628e-03;
   1075          1.1  kardel 
   1076          1.1  kardel 	/*
   1077          1.1  kardel 	 * The 1000/1200 sync signals are demodulated using a pair of
   1078          1.1  kardel 	 * quadrature multipliers and matched filters. However,
   1079          1.1  kardel 	 * synchronous demodulation at these frequencies is impractical,
   1080          1.1  kardel 	 * so only the signal amplitude is used. The I and Q quadrature
   1081          1.1  kardel 	 * sync signals are produced by multiplying the filtered signal
   1082          1.1  kardel 	 * by 1000-Hz (WWV) and 1200-Hz (WWVH) sine and cosine signals,
   1083          1.1  kardel 	 * respectively. The WWV and WWVH signals are processed by 800-
   1084          1.1  kardel 	 * ms synchronous matched filters and combined to produce the
   1085          1.1  kardel 	 * minute sync signal and detect which one (or both) the WWV or
   1086          1.1  kardel 	 * WWVH signal is present. The WWV and WWVH signals are also
   1087          1.1  kardel 	 * processed by 5-ms synchronous matched filters and combined to
   1088          1.1  kardel 	 * produce the second sync signal. The signals are scaled to
   1089          1.1  kardel 	 * produce unit energy at the maximum value.
   1090          1.1  kardel 	 *
   1091          1.1  kardel 	 * Note the master timing ramps, which run continuously. The
   1092          1.1  kardel 	 * minute counter (mphase) counts the samples in the minute,
   1093          1.1  kardel 	 * while the second counter (epoch) counts the samples in the
   1094          1.1  kardel 	 * second.
   1095          1.1  kardel 	 */
   1096  1.1.1.1.6.1    yamt 	up->mphase = (up->mphase + 1) % WWV_MIN;
   1097  1.1.1.1.6.1    yamt 	epoch = up->mphase % WWV_SEC;
   1098          1.1  kardel 
   1099          1.1  kardel 	/*
   1100          1.1  kardel 	 * WWV
   1101          1.1  kardel 	 */
   1102          1.1  kardel 	i = csinptr;
   1103          1.1  kardel 	csinptr = (csinptr + IN1000) % 80;
   1104          1.1  kardel 
   1105          1.1  kardel 	dtemp = sintab[i] * syncx / (MS / 2.);
   1106          1.1  kardel 	ciamp -= cibuf[jptr];
   1107          1.1  kardel 	cibuf[jptr] = dtemp;
   1108          1.1  kardel 	ciamp += dtemp;
   1109          1.1  kardel 	csiamp -= csibuf[kptr];
   1110          1.1  kardel 	csibuf[kptr] = dtemp;
   1111          1.1  kardel 	csiamp += dtemp;
   1112          1.1  kardel 
   1113          1.1  kardel 	i = (i + 20) % 80;
   1114          1.1  kardel 	dtemp = sintab[i] * syncx / (MS / 2.);
   1115          1.1  kardel 	cqamp -= cqbuf[jptr];
   1116          1.1  kardel 	cqbuf[jptr] = dtemp;
   1117          1.1  kardel 	cqamp += dtemp;
   1118          1.1  kardel 	csqamp -= csqbuf[kptr];
   1119          1.1  kardel 	csqbuf[kptr] = dtemp;
   1120          1.1  kardel 	csqamp += dtemp;
   1121          1.1  kardel 
   1122          1.1  kardel 	sp = &up->mitig[up->achan].wwv;
   1123          1.1  kardel 	sp->amp = sqrt(ciamp * ciamp + cqamp * cqamp) / SYNCYC;
   1124          1.1  kardel 	if (!(up->status & MSYNC))
   1125  1.1.1.1.6.1    yamt 		wwv_qrz(peer, sp, (int)(pp->fudgetime1 * WWV_SEC));
   1126          1.1  kardel 
   1127          1.1  kardel 	/*
   1128          1.1  kardel 	 * WWVH
   1129          1.1  kardel 	 */
   1130          1.1  kardel 	i = hsinptr;
   1131          1.1  kardel 	hsinptr = (hsinptr + IN1200) % 80;
   1132          1.1  kardel 
   1133          1.1  kardel 	dtemp = sintab[i] * syncx / (MS / 2.);
   1134          1.1  kardel 	hiamp -= hibuf[jptr];
   1135          1.1  kardel 	hibuf[jptr] = dtemp;
   1136          1.1  kardel 	hiamp += dtemp;
   1137          1.1  kardel 	hsiamp -= hsibuf[kptr];
   1138          1.1  kardel 	hsibuf[kptr] = dtemp;
   1139          1.1  kardel 	hsiamp += dtemp;
   1140          1.1  kardel 
   1141          1.1  kardel 	i = (i + 20) % 80;
   1142          1.1  kardel 	dtemp = sintab[i] * syncx / (MS / 2.);
   1143          1.1  kardel 	hqamp -= hqbuf[jptr];
   1144          1.1  kardel 	hqbuf[jptr] = dtemp;
   1145          1.1  kardel 	hqamp += dtemp;
   1146          1.1  kardel 	hsqamp -= hsqbuf[kptr];
   1147          1.1  kardel 	hsqbuf[kptr] = dtemp;
   1148          1.1  kardel 	hsqamp += dtemp;
   1149          1.1  kardel 
   1150          1.1  kardel 	rp = &up->mitig[up->achan].wwvh;
   1151          1.1  kardel 	rp->amp = sqrt(hiamp * hiamp + hqamp * hqamp) / SYNCYC;
   1152          1.1  kardel 	if (!(up->status & MSYNC))
   1153  1.1.1.1.6.1    yamt 		wwv_qrz(peer, rp, (int)(pp->fudgetime2 * WWV_SEC));
   1154          1.1  kardel 	jptr = (jptr + 1) % SYNSIZ;
   1155          1.1  kardel 	kptr = (kptr + 1) % TCKSIZ;
   1156          1.1  kardel 
   1157          1.1  kardel 	/*
   1158          1.1  kardel 	 * The following section is called once per minute. It does
   1159          1.1  kardel 	 * housekeeping and timeout functions and empties the dustbins.
   1160          1.1  kardel 	 */
   1161          1.1  kardel 	if (up->mphase == 0) {
   1162          1.1  kardel 		up->watch++;
   1163          1.1  kardel 		if (!(up->status & MSYNC)) {
   1164          1.1  kardel 
   1165          1.1  kardel 			/*
   1166          1.1  kardel 			 * If minute sync has not been acquired before
   1167          1.1  kardel 			 * ACQSN timeout (6 min), or if no signal is
   1168          1.1  kardel 			 * heard, the program cycles to the next
   1169          1.1  kardel 			 * frequency and tries again.
   1170          1.1  kardel 			 */
   1171          1.1  kardel 			if (!wwv_newchan(peer))
   1172          1.1  kardel 				up->watch = 0;
   1173          1.1  kardel 		} else {
   1174          1.1  kardel 
   1175          1.1  kardel 			/*
   1176          1.1  kardel 			 * If the leap bit is set, set the minute epoch
   1177          1.1  kardel 			 * back one second so the station processes
   1178          1.1  kardel 			 * don't miss a beat.
   1179          1.1  kardel 			 */
   1180          1.1  kardel 			if (up->status & LEPSEC) {
   1181  1.1.1.1.6.1    yamt 				up->mphase -= WWV_SEC;
   1182          1.1  kardel 				if (up->mphase < 0)
   1183  1.1.1.1.6.1    yamt 					up->mphase += WWV_MIN;
   1184          1.1  kardel 			}
   1185          1.1  kardel 		}
   1186          1.1  kardel 	}
   1187          1.1  kardel 
   1188          1.1  kardel 	/*
   1189          1.1  kardel 	 * When the channel metric reaches threshold and the second
   1190          1.1  kardel 	 * counter matches the minute epoch within the second, the
   1191          1.1  kardel 	 * driver has synchronized to the station. The second number is
   1192          1.1  kardel 	 * the remaining seconds until the next minute epoch, while the
   1193          1.1  kardel 	 * sync epoch is zero. Watch out for the first second; if
   1194          1.1  kardel 	 * already synchronized to the second, the buffered sync epoch
   1195          1.1  kardel 	 * must be set.
   1196          1.1  kardel 	 *
   1197          1.1  kardel 	 * Note the guard interval is 200 ms; if for some reason the
   1198          1.1  kardel 	 * clock drifts more than that, it might wind up in the wrong
   1199          1.1  kardel 	 * second. If the maximum frequency error is not more than about
   1200          1.1  kardel 	 * 1 PPM, the clock can go as much as two days while still in
   1201          1.1  kardel 	 * the same second.
   1202          1.1  kardel 	 */
   1203          1.1  kardel 	if (up->status & MSYNC) {
   1204          1.1  kardel 		wwv_epoch(peer);
   1205          1.1  kardel 	} else if (up->sptr != NULL) {
   1206          1.1  kardel 		sp = up->sptr;
   1207  1.1.1.1.6.1    yamt 		if (sp->metric >= TTHR && epoch == sp->mepoch % WWV_SEC)
   1208          1.1  kardel  		    {
   1209  1.1.1.1.6.1    yamt 			up->rsec = (60 - sp->mepoch / WWV_SEC) % 60;
   1210          1.1  kardel 			up->rphase = 0;
   1211          1.1  kardel 			up->status |= MSYNC;
   1212          1.1  kardel 			up->watch = 0;
   1213          1.1  kardel 			if (!(up->status & SSYNC))
   1214          1.1  kardel 				up->repoch = up->yepoch = epoch;
   1215          1.1  kardel 			else
   1216          1.1  kardel 				up->repoch = up->yepoch;
   1217          1.1  kardel 
   1218          1.1  kardel 		}
   1219          1.1  kardel 	}
   1220          1.1  kardel 
   1221          1.1  kardel 	/*
   1222          1.1  kardel 	 * The second sync pulse is extracted using 5-ms (40 sample) FIR
   1223          1.1  kardel 	 * matched filters at 1000 Hz for WWV or 1200 Hz for WWVH. This
   1224          1.1  kardel 	 * pulse is used for the most precise synchronization, since if
   1225          1.1  kardel 	 * provides a resolution of one sample (125 us). The filters run
   1226          1.1  kardel 	 * only if the station has been reliably determined.
   1227          1.1  kardel 	 */
   1228          1.1  kardel 	if (up->status & SELV)
   1229          1.1  kardel 		mfsync = sqrt(csiamp * csiamp + csqamp * csqamp) /
   1230          1.1  kardel 		    TCKCYC;
   1231          1.1  kardel 	else if (up->status & SELH)
   1232          1.1  kardel 		mfsync = sqrt(hsiamp * hsiamp + hsqamp * hsqamp) /
   1233          1.1  kardel 		    TCKCYC;
   1234          1.1  kardel 	else
   1235          1.1  kardel 		mfsync = 0;
   1236          1.1  kardel 
   1237          1.1  kardel 	/*
   1238          1.1  kardel 	 * Enhance the seconds sync pulse using a 1-s (8000-sample) comb
   1239          1.1  kardel 	 * filter. Correct for the FIR matched filter delay, which is 5
   1240          1.1  kardel 	 * ms for both the WWV and WWVH filters, and also for the
   1241          1.1  kardel 	 * propagation delay. Once each second look for second sync. If
   1242          1.1  kardel 	 * not in minute sync, fiddle the codec gain. Note the SNR is
   1243          1.1  kardel 	 * computed from the maximum sample and the envelope of the
   1244          1.1  kardel 	 * sample 6 ms before it, so if we slip more than a cycle the
   1245          1.1  kardel 	 * SNR should plummet. The signal is scaled to produce unit
   1246          1.1  kardel 	 * energy at the maximum value.
   1247          1.1  kardel 	 */
   1248          1.1  kardel 	dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
   1249          1.1  kardel 	    up->avgint);
   1250          1.1  kardel 	if (dtemp > epomax) {
   1251          1.1  kardel 		int	j;
   1252          1.1  kardel 
   1253          1.1  kardel 		epomax = dtemp;
   1254          1.1  kardel 		epopos = epoch;
   1255          1.1  kardel 		j = epoch - 6 * MS;
   1256          1.1  kardel 		if (j < 0)
   1257  1.1.1.1.6.1    yamt 			j += WWV_SEC;
   1258          1.1  kardel 		nxtmax = fabs(epobuf[j]);
   1259          1.1  kardel 	}
   1260          1.1  kardel 	if (epoch == 0) {
   1261          1.1  kardel 		up->epomax = epomax;
   1262          1.1  kardel 		up->eposnr = wwv_snr(epomax, nxtmax);
   1263          1.1  kardel 		epopos -= TCKCYC * MS;
   1264          1.1  kardel 		if (epopos < 0)
   1265  1.1.1.1.6.1    yamt 			epopos += WWV_SEC;
   1266          1.1  kardel 		wwv_endpoc(peer, epopos);
   1267          1.1  kardel 		if (!(up->status & SSYNC))
   1268          1.1  kardel 			up->alarm |= SYNERR;
   1269          1.1  kardel 		epomax = 0;
   1270          1.1  kardel 		if (!(up->status & MSYNC))
   1271          1.1  kardel 			wwv_gain(peer);
   1272          1.1  kardel 	}
   1273          1.1  kardel }
   1274          1.1  kardel 
   1275          1.1  kardel 
   1276          1.1  kardel /*
   1277          1.1  kardel  * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse
   1278          1.1  kardel  *
   1279          1.1  kardel  * This routine implements a virtual station process used to acquire
   1280          1.1  kardel  * minute sync and to mitigate among the ten frequency and station
   1281          1.1  kardel  * combinations. During minute sync acquisition the process probes each
   1282          1.1  kardel  * frequency and station in turn for the minute pulse, which
   1283          1.1  kardel  * involves searching through the entire 480,000-sample minute. The
   1284          1.1  kardel  * process finds the maximum signal and RMS noise plus signal. Then, the
   1285          1.1  kardel  * actual noise is determined by subtracting the energy of the matched
   1286          1.1  kardel  * filter.
   1287          1.1  kardel  *
   1288          1.1  kardel  * Students of radar receiver technology will discover this algorithm
   1289          1.1  kardel  * amounts to a range-gate discriminator. A valid pulse must have peak
   1290          1.1  kardel  * amplitude at least QTHR (2500) and SNR at least QSNR (20) dB and the
   1291          1.1  kardel  * difference between the current and previous epoch must be less than
   1292          1.1  kardel  * AWND (20 ms). Note that the discriminator peak occurs about 800 ms
   1293          1.1  kardel  * into the second, so the timing is retarded to the previous second
   1294          1.1  kardel  * epoch.
   1295          1.1  kardel  */
   1296          1.1  kardel static void
   1297          1.1  kardel wwv_qrz(
   1298          1.1  kardel 	struct peer *peer,	/* peer structure pointer */
   1299          1.1  kardel 	struct sync *sp,	/* sync channel structure */
   1300          1.1  kardel 	int	pdelay		/* propagation delay (samples) */
   1301          1.1  kardel 	)
   1302          1.1  kardel {
   1303          1.1  kardel 	struct refclockproc *pp;
   1304          1.1  kardel 	struct wwvunit *up;
   1305          1.1  kardel 	char	tbuf[TBUF];	/* monitor buffer */
   1306          1.1  kardel 	long	epoch;
   1307          1.1  kardel 
   1308          1.1  kardel 	pp = peer->procptr;
   1309  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   1310          1.1  kardel 
   1311          1.1  kardel 	/*
   1312          1.1  kardel 	 * Find the sample with peak amplitude, which defines the minute
   1313          1.1  kardel 	 * epoch. Accumulate all samples to determine the total noise
   1314          1.1  kardel 	 * energy.
   1315          1.1  kardel 	 */
   1316          1.1  kardel 	epoch = up->mphase - pdelay - SYNSIZ;
   1317          1.1  kardel 	if (epoch < 0)
   1318  1.1.1.1.6.1    yamt 		epoch += WWV_MIN;
   1319          1.1  kardel 	if (sp->amp > sp->maxeng) {
   1320          1.1  kardel 		sp->maxeng = sp->amp;
   1321          1.1  kardel 		sp->pos = epoch;
   1322          1.1  kardel 	}
   1323          1.1  kardel 	sp->noieng += sp->amp;
   1324          1.1  kardel 
   1325          1.1  kardel 	/*
   1326          1.1  kardel 	 * At the end of the minute, determine the epoch of the minute
   1327          1.1  kardel 	 * sync pulse, as well as the difference between the current and
   1328          1.1  kardel 	 * previous epoches due to the intrinsic frequency error plus
   1329          1.1  kardel 	 * jitter. When calculating the SNR, subtract the pulse energy
   1330          1.1  kardel 	 * from the total noise energy and then normalize.
   1331          1.1  kardel 	 */
   1332          1.1  kardel 	if (up->mphase == 0) {
   1333          1.1  kardel 		sp->synmax = sp->maxeng;
   1334          1.1  kardel 		sp->synsnr = wwv_snr(sp->synmax, (sp->noieng -
   1335  1.1.1.1.6.1    yamt 		    sp->synmax) / WWV_MIN);
   1336          1.1  kardel 		if (sp->count == 0)
   1337          1.1  kardel 			sp->lastpos = sp->pos;
   1338  1.1.1.1.6.1    yamt 		epoch = (sp->pos - sp->lastpos) % WWV_MIN;
   1339          1.1  kardel 		sp->reach <<= 1;
   1340          1.1  kardel 		if (sp->reach & (1 << AMAX))
   1341          1.1  kardel 			sp->count--;
   1342          1.1  kardel 		if (sp->synmax > ATHR && sp->synsnr > ASNR) {
   1343  1.1.1.1.6.1    yamt 			if (labs(epoch) < AWND * MS) {
   1344          1.1  kardel 				sp->reach |= 1;
   1345          1.1  kardel 				sp->count++;
   1346          1.1  kardel 				sp->mepoch = sp->lastpos = sp->pos;
   1347          1.1  kardel 			} else if (sp->count == 1) {
   1348          1.1  kardel 				sp->lastpos = sp->pos;
   1349          1.1  kardel 			}
   1350          1.1  kardel 		}
   1351          1.1  kardel 		if (up->watch > ACQSN)
   1352          1.1  kardel 			sp->metric = 0;
   1353          1.1  kardel 		else
   1354          1.1  kardel 			sp->metric = wwv_metric(sp);
   1355          1.1  kardel 		if (pp->sloppyclockflag & CLK_FLAG4) {
   1356  1.1.1.1.6.1    yamt 			snprintf(tbuf, sizeof(tbuf),
   1357          1.1  kardel 			    "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %ld %ld",
   1358          1.1  kardel 			    up->status, up->gain, sp->refid,
   1359          1.1  kardel 			    sp->reach & 0xffff, sp->metric, sp->synmax,
   1360  1.1.1.1.6.1    yamt 			    sp->synsnr, sp->pos % WWV_SEC, epoch);
   1361          1.1  kardel 			record_clock_stats(&peer->srcadr, tbuf);
   1362          1.1  kardel #ifdef DEBUG
   1363          1.1  kardel 			if (debug)
   1364          1.1  kardel 				printf("%s\n", tbuf);
   1365          1.1  kardel #endif /* DEBUG */
   1366          1.1  kardel 		}
   1367          1.1  kardel 		sp->maxeng = sp->noieng = 0;
   1368          1.1  kardel 	}
   1369          1.1  kardel }
   1370          1.1  kardel 
   1371          1.1  kardel 
   1372          1.1  kardel /*
   1373          1.1  kardel  * wwv_endpoc - identify and acquire second sync pulse
   1374          1.1  kardel  *
   1375          1.1  kardel  * This routine is called at the end of the second sync interval. It
   1376          1.1  kardel  * determines the second sync epoch position within the second and
   1377          1.1  kardel  * disciplines the sample clock using a frequency-lock loop (FLL).
   1378          1.1  kardel  *
   1379          1.1  kardel  * Second sync is determined in the RF input routine as the maximum
   1380          1.1  kardel  * over all 8000 samples in the second comb filter. To assure accurate
   1381          1.1  kardel  * and reliable time and frequency discipline, this routine performs a
   1382          1.1  kardel  * great deal of heavy-handed heuristic data filtering and grooming.
   1383          1.1  kardel  */
   1384          1.1  kardel static void
   1385          1.1  kardel wwv_endpoc(
   1386          1.1  kardel 	struct peer *peer,	/* peer structure pointer */
   1387          1.1  kardel 	int epopos		/* epoch max position */
   1388          1.1  kardel 	)
   1389          1.1  kardel {
   1390          1.1  kardel 	struct refclockproc *pp;
   1391          1.1  kardel 	struct wwvunit *up;
   1392          1.1  kardel 	static int epoch_mf[3]; /* epoch median filter */
   1393          1.1  kardel 	static int tepoch;	/* current second epoch */
   1394          1.1  kardel  	static int xepoch;	/* last second epoch */
   1395          1.1  kardel  	static int zepoch;	/* last run epoch */
   1396          1.1  kardel 	static int zcount;	/* last run end time */
   1397          1.1  kardel 	static int scount;	/* seconds counter */
   1398          1.1  kardel 	static int syncnt;	/* run length counter */
   1399          1.1  kardel 	static int maxrun;	/* longest run length */
   1400          1.1  kardel 	static int mepoch;	/* longest run end epoch */
   1401          1.1  kardel 	static int mcount;	/* longest run end time */
   1402          1.1  kardel 	static int avgcnt;	/* averaging interval counter */
   1403          1.1  kardel 	static int avginc;	/* averaging ratchet */
   1404          1.1  kardel 	static int iniflg;	/* initialization flag */
   1405          1.1  kardel 	char tbuf[TBUF];		/* monitor buffer */
   1406          1.1  kardel 	double dtemp;
   1407          1.1  kardel 	int tmp2;
   1408          1.1  kardel 
   1409          1.1  kardel 	pp = peer->procptr;
   1410  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   1411          1.1  kardel 	if (!iniflg) {
   1412          1.1  kardel 		iniflg = 1;
   1413  1.1.1.1.6.1    yamt 		ZERO(epoch_mf);
   1414          1.1  kardel 	}
   1415          1.1  kardel 
   1416          1.1  kardel 	/*
   1417          1.1  kardel 	 * If the signal amplitude or SNR fall below thresholds, dim the
   1418          1.1  kardel 	 * second sync lamp and wait for hotter ions. If no stations are
   1419          1.1  kardel 	 * heard, we are either in a probe cycle or the ions are really
   1420          1.1  kardel 	 * cold.
   1421          1.1  kardel 	 */
   1422          1.1  kardel 	scount++;
   1423          1.1  kardel 	if (up->epomax < STHR || up->eposnr < SSNR) {
   1424          1.1  kardel 		up->status &= ~(SSYNC | FGATE);
   1425          1.1  kardel 		avgcnt = syncnt = maxrun = 0;
   1426          1.1  kardel 		return;
   1427          1.1  kardel 	}
   1428          1.1  kardel 	if (!(up->status & (SELV | SELH)))
   1429          1.1  kardel 		return;
   1430          1.1  kardel 
   1431          1.1  kardel 	/*
   1432          1.1  kardel 	 * A three-stage median filter is used to help denoise the
   1433          1.1  kardel 	 * second sync pulse. The median sample becomes the candidate
   1434          1.1  kardel 	 * epoch.
   1435          1.1  kardel 	 */
   1436          1.1  kardel 	epoch_mf[2] = epoch_mf[1];
   1437          1.1  kardel 	epoch_mf[1] = epoch_mf[0];
   1438          1.1  kardel 	epoch_mf[0] = epopos;
   1439          1.1  kardel 	if (epoch_mf[0] > epoch_mf[1]) {
   1440          1.1  kardel 		if (epoch_mf[1] > epoch_mf[2])
   1441          1.1  kardel 			tepoch = epoch_mf[1];	/* 0 1 2 */
   1442          1.1  kardel 		else if (epoch_mf[2] > epoch_mf[0])
   1443          1.1  kardel 			tepoch = epoch_mf[0];	/* 2 0 1 */
   1444          1.1  kardel 		else
   1445          1.1  kardel 			tepoch = epoch_mf[2];	/* 0 2 1 */
   1446          1.1  kardel 	} else {
   1447          1.1  kardel 		if (epoch_mf[1] < epoch_mf[2])
   1448          1.1  kardel 			tepoch = epoch_mf[1];	/* 2 1 0 */
   1449          1.1  kardel 		else if (epoch_mf[2] < epoch_mf[0])
   1450          1.1  kardel 			tepoch = epoch_mf[0];	/* 1 0 2 */
   1451          1.1  kardel 		else
   1452          1.1  kardel 			tepoch = epoch_mf[2];	/* 1 2 0 */
   1453          1.1  kardel 	}
   1454          1.1  kardel 
   1455          1.1  kardel 
   1456          1.1  kardel 	/*
   1457          1.1  kardel 	 * If the epoch candidate is the same as the last one, increment
   1458          1.1  kardel 	 * the run counter. If not, save the length, epoch and end
   1459          1.1  kardel 	 * time of the current run for use later and reset the counter.
   1460          1.1  kardel 	 * The epoch is considered valid if the run is at least SCMP
   1461          1.1  kardel 	 * (10) s, the minute is synchronized and the interval since the
   1462          1.1  kardel 	 * last epoch  is not greater than the averaging interval. Thus,
   1463          1.1  kardel 	 * after a long absence, the program will wait a full averaging
   1464          1.1  kardel 	 * interval while the comb filter charges up and noise
   1465          1.1  kardel 	 * dissapates..
   1466          1.1  kardel 	 */
   1467  1.1.1.1.6.1    yamt 	tmp2 = (tepoch - xepoch) % WWV_SEC;
   1468          1.1  kardel 	if (tmp2 == 0) {
   1469          1.1  kardel 		syncnt++;
   1470          1.1  kardel 		if (syncnt > SCMP && up->status & MSYNC && (up->status &
   1471          1.1  kardel 		    FGATE || scount - zcount <= up->avgint)) {
   1472          1.1  kardel 			up->status |= SSYNC;
   1473          1.1  kardel 			up->yepoch = tepoch;
   1474          1.1  kardel 		}
   1475          1.1  kardel 	} else if (syncnt >= maxrun) {
   1476          1.1  kardel 		maxrun = syncnt;
   1477          1.1  kardel 		mcount = scount;
   1478          1.1  kardel 		mepoch = xepoch;
   1479          1.1  kardel 		syncnt = 0;
   1480          1.1  kardel 	}
   1481          1.1  kardel 	if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
   1482          1.1  kardel 	    MSYNC)) {
   1483  1.1.1.1.6.1    yamt 		snprintf(tbuf, sizeof(tbuf),
   1484          1.1  kardel 		    "wwv1 %04x %3d %4d %5.0f %5.1f %5d %4d %4d %4d",
   1485          1.1  kardel 		    up->status, up->gain, tepoch, up->epomax,
   1486          1.1  kardel 		    up->eposnr, tmp2, avgcnt, syncnt,
   1487          1.1  kardel 		    maxrun);
   1488          1.1  kardel 		record_clock_stats(&peer->srcadr, tbuf);
   1489          1.1  kardel #ifdef DEBUG
   1490          1.1  kardel 		if (debug)
   1491          1.1  kardel 			printf("%s\n", tbuf);
   1492          1.1  kardel #endif /* DEBUG */
   1493          1.1  kardel 	}
   1494          1.1  kardel 	avgcnt++;
   1495          1.1  kardel 	if (avgcnt < up->avgint) {
   1496          1.1  kardel 		xepoch = tepoch;
   1497          1.1  kardel 		return;
   1498          1.1  kardel 	}
   1499          1.1  kardel 
   1500          1.1  kardel 	/*
   1501          1.1  kardel 	 * The sample clock frequency is disciplined using a first-order
   1502          1.1  kardel 	 * feedback loop with time constant consistent with the Allan
   1503          1.1  kardel 	 * intercept of typical computer clocks. During each averaging
   1504          1.1  kardel 	 * interval the candidate epoch at the end of the longest run is
   1505          1.1  kardel 	 * determined. If the longest run is zero, all epoches in the
   1506          1.1  kardel 	 * interval are different, so the candidate epoch is the current
   1507          1.1  kardel 	 * epoch. The frequency update is computed from the candidate
   1508          1.1  kardel 	 * epoch difference (125-us units) and time difference (seconds)
   1509          1.1  kardel 	 * between updates.
   1510          1.1  kardel 	 */
   1511          1.1  kardel 	if (syncnt >= maxrun) {
   1512          1.1  kardel 		maxrun = syncnt;
   1513          1.1  kardel 		mcount = scount;
   1514          1.1  kardel 		mepoch = xepoch;
   1515          1.1  kardel 	}
   1516          1.1  kardel 	xepoch = tepoch;
   1517          1.1  kardel 	if (maxrun == 0) {
   1518          1.1  kardel 		mepoch = tepoch;
   1519          1.1  kardel 		mcount = scount;
   1520          1.1  kardel 	}
   1521          1.1  kardel 
   1522          1.1  kardel 	/*
   1523          1.1  kardel 	 * The master clock runs at the codec sample frequency of 8000
   1524          1.1  kardel 	 * Hz, so the intrinsic time resolution is 125 us. The frequency
   1525          1.1  kardel 	 * resolution ranges from 18 PPM at the minimum averaging
   1526          1.1  kardel 	 * interval of 8 s to 0.12 PPM at the maximum interval of 1024
   1527          1.1  kardel 	 * s. An offset update is determined at the end of the longest
   1528          1.1  kardel 	 * run in each averaging interval. The frequency adjustment is
   1529          1.1  kardel 	 * computed from the difference between offset updates and the
   1530          1.1  kardel 	 * interval between them.
   1531          1.1  kardel 	 *
   1532          1.1  kardel 	 * The maximum frequency adjustment ranges from 187 PPM at the
   1533          1.1  kardel 	 * minimum interval to 1.5 PPM at the maximum. If the adjustment
   1534          1.1  kardel 	 * exceeds the maximum, the update is discarded and the
   1535          1.1  kardel 	 * hysteresis counter is decremented. Otherwise, the frequency
   1536          1.1  kardel 	 * is incremented by the adjustment, but clamped to the maximum
   1537          1.1  kardel 	 * 187.5 PPM. If the update is less than half the maximum, the
   1538          1.1  kardel 	 * hysteresis counter is incremented. If the counter increments
   1539          1.1  kardel 	 * to +3, the averaging interval is doubled and the counter set
   1540          1.1  kardel 	 * to zero; if it decrements to -3, the interval is halved and
   1541          1.1  kardel 	 * the counter set to zero.
   1542          1.1  kardel 	 */
   1543  1.1.1.1.6.1    yamt 	dtemp = (mepoch - zepoch) % WWV_SEC;
   1544          1.1  kardel 	if (up->status & FGATE) {
   1545  1.1.1.1.6.1    yamt 		if (fabs(dtemp) < MAXFREQ * MINAVG) {
   1546          1.1  kardel 			up->freq += (dtemp / 2.) / ((mcount - zcount) *
   1547          1.1  kardel 			    FCONST);
   1548          1.1  kardel 			if (up->freq > MAXFREQ)
   1549          1.1  kardel 				up->freq = MAXFREQ;
   1550          1.1  kardel 			else if (up->freq < -MAXFREQ)
   1551          1.1  kardel 				up->freq = -MAXFREQ;
   1552  1.1.1.1.6.1    yamt 			if (fabs(dtemp) < MAXFREQ * MINAVG / 2.) {
   1553          1.1  kardel 				if (avginc < 3) {
   1554          1.1  kardel 					avginc++;
   1555          1.1  kardel 				} else {
   1556          1.1  kardel 					if (up->avgint < MAXAVG) {
   1557          1.1  kardel 						up->avgint <<= 1;
   1558          1.1  kardel 						avginc = 0;
   1559          1.1  kardel 					}
   1560          1.1  kardel 				}
   1561          1.1  kardel 			}
   1562          1.1  kardel 		} else {
   1563          1.1  kardel 			if (avginc > -3) {
   1564          1.1  kardel 				avginc--;
   1565          1.1  kardel 			} else {
   1566          1.1  kardel 				if (up->avgint > MINAVG) {
   1567          1.1  kardel 					up->avgint >>= 1;
   1568          1.1  kardel 					avginc = 0;
   1569          1.1  kardel 				}
   1570          1.1  kardel 			}
   1571          1.1  kardel 		}
   1572          1.1  kardel 	}
   1573          1.1  kardel 	if (pp->sloppyclockflag & CLK_FLAG4) {
   1574  1.1.1.1.6.1    yamt 		snprintf(tbuf, sizeof(tbuf),
   1575          1.1  kardel 		    "wwv2 %04x %5.0f %5.1f %5d %4d %4d %4d %4.0f %7.2f",
   1576          1.1  kardel 		    up->status, up->epomax, up->eposnr, mepoch,
   1577          1.1  kardel 		    up->avgint, maxrun, mcount - zcount, dtemp,
   1578  1.1.1.1.6.1    yamt 		    up->freq * 1e6 / WWV_SEC);
   1579          1.1  kardel 		record_clock_stats(&peer->srcadr, tbuf);
   1580          1.1  kardel #ifdef DEBUG
   1581          1.1  kardel 		if (debug)
   1582          1.1  kardel 			printf("%s\n", tbuf);
   1583          1.1  kardel #endif /* DEBUG */
   1584          1.1  kardel 	}
   1585          1.1  kardel 
   1586          1.1  kardel 	/*
   1587          1.1  kardel 	 * This is a valid update; set up for the next interval.
   1588          1.1  kardel 	 */
   1589          1.1  kardel 	up->status |= FGATE;
   1590          1.1  kardel 	zepoch = mepoch;
   1591          1.1  kardel 	zcount = mcount;
   1592          1.1  kardel 	avgcnt = syncnt = maxrun = 0;
   1593          1.1  kardel }
   1594          1.1  kardel 
   1595          1.1  kardel 
   1596          1.1  kardel /*
   1597          1.1  kardel  * wwv_epoch - epoch scanner
   1598          1.1  kardel  *
   1599          1.1  kardel  * This routine extracts data signals from the 100-Hz subcarrier. It
   1600          1.1  kardel  * scans the receiver second epoch to determine the signal amplitudes
   1601          1.1  kardel  * and pulse timings. Receiver synchronization is determined by the
   1602          1.1  kardel  * minute sync pulse detected in the wwv_rf() routine and the second
   1603          1.1  kardel  * sync pulse detected in the wwv_epoch() routine. The transmitted
   1604          1.1  kardel  * signals are delayed by the propagation delay, receiver delay and
   1605          1.1  kardel  * filter delay of this program. Delay corrections are introduced
   1606          1.1  kardel  * separately for WWV and WWVH.
   1607          1.1  kardel  *
   1608          1.1  kardel  * Most communications radios use a highpass filter in the audio stages,
   1609          1.1  kardel  * which can do nasty things to the subcarrier phase relative to the
   1610          1.1  kardel  * sync pulses. Therefore, the data subcarrier reference phase is
   1611          1.1  kardel  * disciplined using the hardlimited quadrature-phase signal sampled at
   1612          1.1  kardel  * the same time as the in-phase signal. The phase tracking loop uses
   1613          1.1  kardel  * phase adjustments of plus-minus one sample (125 us).
   1614          1.1  kardel  */
   1615          1.1  kardel static void
   1616          1.1  kardel wwv_epoch(
   1617          1.1  kardel 	struct peer *peer	/* peer structure pointer */
   1618          1.1  kardel 	)
   1619          1.1  kardel {
   1620          1.1  kardel 	struct refclockproc *pp;
   1621          1.1  kardel 	struct wwvunit *up;
   1622          1.1  kardel 	struct chan *cp;
   1623          1.1  kardel 	static double sigmin, sigzer, sigone, engmax, engmin;
   1624          1.1  kardel 
   1625          1.1  kardel 	pp = peer->procptr;
   1626  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   1627          1.1  kardel 
   1628          1.1  kardel 	/*
   1629          1.1  kardel 	 * Find the maximum minute sync pulse energy for both the
   1630          1.1  kardel 	 * WWV and WWVH stations. This will be used later for channel
   1631          1.1  kardel 	 * and station mitigation. Also set the seconds epoch at 800 ms
   1632          1.1  kardel 	 * well before the end of the second to make sure we never set
   1633          1.1  kardel 	 * the epoch backwards.
   1634          1.1  kardel 	 */
   1635          1.1  kardel 	cp = &up->mitig[up->achan];
   1636          1.1  kardel 	if (cp->wwv.amp > cp->wwv.syneng)
   1637          1.1  kardel 		cp->wwv.syneng = cp->wwv.amp;
   1638          1.1  kardel 	if (cp->wwvh.amp > cp->wwvh.syneng)
   1639          1.1  kardel 		cp->wwvh.syneng = cp->wwvh.amp;
   1640          1.1  kardel 	if (up->rphase == 800 * MS)
   1641          1.1  kardel 		up->repoch = up->yepoch;
   1642          1.1  kardel 
   1643          1.1  kardel 	/*
   1644          1.1  kardel 	 * Use the signal amplitude at epoch 15 ms as the noise floor.
   1645          1.1  kardel 	 * This gives a guard time of +-15 ms from the beginning of the
   1646          1.1  kardel 	 * second until the second pulse rises at 30 ms. There is a
   1647          1.1  kardel 	 * compromise here; we want to delay the sample as long as
   1648          1.1  kardel 	 * possible to give the radio time to change frequency and the
   1649          1.1  kardel 	 * AGC to stabilize, but as early as possible if the second
   1650          1.1  kardel 	 * epoch is not exact.
   1651          1.1  kardel 	 */
   1652          1.1  kardel 	if (up->rphase == 15 * MS)
   1653          1.1  kardel 		sigmin = sigzer = sigone = up->irig;
   1654          1.1  kardel 
   1655          1.1  kardel 	/*
   1656          1.1  kardel 	 * Latch the data signal at 200 ms. Keep this around until the
   1657          1.1  kardel 	 * end of the second. Use the signal energy as the peak to
   1658          1.1  kardel 	 * compute the SNR. Use the Q sample to adjust the 100-Hz
   1659          1.1  kardel 	 * reference oscillator phase.
   1660          1.1  kardel 	 */
   1661          1.1  kardel 	if (up->rphase == 200 * MS) {
   1662          1.1  kardel 		sigzer = up->irig;
   1663          1.1  kardel 		engmax = sqrt(up->irig * up->irig + up->qrig *
   1664          1.1  kardel 		    up->qrig);
   1665          1.1  kardel 		up->datpha = up->qrig / up->avgint;
   1666          1.1  kardel 		if (up->datpha >= 0) {
   1667          1.1  kardel 			up->datapt++;
   1668          1.1  kardel 			if (up->datapt >= 80)
   1669          1.1  kardel 				up->datapt -= 80;
   1670          1.1  kardel 		} else {
   1671          1.1  kardel 			up->datapt--;
   1672          1.1  kardel 			if (up->datapt < 0)
   1673          1.1  kardel 				up->datapt += 80;
   1674          1.1  kardel 		}
   1675          1.1  kardel 	}
   1676          1.1  kardel 
   1677          1.1  kardel 
   1678          1.1  kardel 	/*
   1679          1.1  kardel 	 * Latch the data signal at 500 ms. Keep this around until the
   1680          1.1  kardel 	 * end of the second.
   1681          1.1  kardel 	 */
   1682          1.1  kardel 	else if (up->rphase == 500 * MS)
   1683          1.1  kardel 		sigone = up->irig;
   1684          1.1  kardel 
   1685          1.1  kardel 	/*
   1686          1.1  kardel 	 * At the end of the second crank the clock state machine and
   1687          1.1  kardel 	 * adjust the codec gain. Note the epoch is buffered from the
   1688          1.1  kardel 	 * center of the second in order to avoid jitter while the
   1689          1.1  kardel 	 * seconds synch is diddling the epoch. Then, determine the true
   1690          1.1  kardel 	 * offset and update the median filter in the driver interface.
   1691          1.1  kardel 	 *
   1692          1.1  kardel 	 * Use the energy at the end of the second as the noise to
   1693          1.1  kardel 	 * compute the SNR for the data pulse. This gives a better
   1694          1.1  kardel 	 * measurement than the beginning of the second, especially when
   1695          1.1  kardel 	 * returning from the probe channel. This gives a guard time of
   1696          1.1  kardel 	 * 30 ms from the decay of the longest pulse to the rise of the
   1697          1.1  kardel 	 * next pulse.
   1698          1.1  kardel 	 */
   1699          1.1  kardel 	up->rphase++;
   1700  1.1.1.1.6.1    yamt 	if (up->mphase % WWV_SEC == up->repoch) {
   1701          1.1  kardel 		up->status &= ~(DGATE | BGATE);
   1702          1.1  kardel 		engmin = sqrt(up->irig * up->irig + up->qrig *
   1703          1.1  kardel 		    up->qrig);
   1704          1.1  kardel 		up->datsig = engmax;
   1705          1.1  kardel 		up->datsnr = wwv_snr(engmax, engmin);
   1706          1.1  kardel 
   1707          1.1  kardel 		/*
   1708          1.1  kardel 		 * If the amplitude or SNR is below threshold, average a
   1709          1.1  kardel 		 * 0 in the the integrators; otherwise, average the
   1710          1.1  kardel 		 * bipolar signal. This is done to avoid noise polution.
   1711          1.1  kardel 		 */
   1712          1.1  kardel 		if (engmax < DTHR || up->datsnr < DSNR) {
   1713          1.1  kardel 			up->status |= DGATE;
   1714          1.1  kardel 			wwv_rsec(peer, 0);
   1715          1.1  kardel 		} else {
   1716          1.1  kardel 			sigzer -= sigone;
   1717          1.1  kardel 			sigone -= sigmin;
   1718          1.1  kardel 			wwv_rsec(peer, sigone - sigzer);
   1719          1.1  kardel 		}
   1720          1.1  kardel 		if (up->status & (DGATE | BGATE))
   1721          1.1  kardel 			up->errcnt++;
   1722          1.1  kardel 		if (up->errcnt > MAXERR)
   1723          1.1  kardel 			up->alarm |= LOWERR;
   1724          1.1  kardel 		wwv_gain(peer);
   1725          1.1  kardel 		cp = &up->mitig[up->achan];
   1726          1.1  kardel 		cp->wwv.syneng = 0;
   1727          1.1  kardel 		cp->wwvh.syneng = 0;
   1728          1.1  kardel 		up->rphase = 0;
   1729          1.1  kardel 	}
   1730          1.1  kardel }
   1731          1.1  kardel 
   1732          1.1  kardel 
   1733          1.1  kardel /*
   1734          1.1  kardel  * wwv_rsec - process receiver second
   1735          1.1  kardel  *
   1736          1.1  kardel  * This routine is called at the end of each receiver second to
   1737          1.1  kardel  * implement the per-second state machine. The machine assembles BCD
   1738          1.1  kardel  * digit bits, decodes miscellaneous bits and dances the leap seconds.
   1739          1.1  kardel  *
   1740          1.1  kardel  * Normally, the minute has 60 seconds numbered 0-59. If the leap
   1741          1.1  kardel  * warning bit is set, the last minute (1439) of 30 June (day 181 or 182
   1742          1.1  kardel  * for leap years) or 31 December (day 365 or 366 for leap years) is
   1743          1.1  kardel  * augmented by one second numbered 60. This is accomplished by
   1744          1.1  kardel  * extending the minute interval by one second and teaching the state
   1745          1.1  kardel  * machine to ignore it.
   1746          1.1  kardel  */
   1747          1.1  kardel static void
   1748          1.1  kardel wwv_rsec(
   1749          1.1  kardel 	struct peer *peer,	/* peer structure pointer */
   1750          1.1  kardel 	double bit
   1751          1.1  kardel 	)
   1752          1.1  kardel {
   1753          1.1  kardel 	static int iniflg;	/* initialization flag */
   1754          1.1  kardel 	static double bcddld[4]; /* BCD data bits */
   1755          1.1  kardel 	static double bitvec[61]; /* bit integrator for misc bits */
   1756          1.1  kardel 	struct refclockproc *pp;
   1757          1.1  kardel 	struct wwvunit *up;
   1758          1.1  kardel 	struct chan *cp;
   1759          1.1  kardel 	struct sync *sp, *rp;
   1760          1.1  kardel 	char	tbuf[TBUF];	/* monitor buffer */
   1761          1.1  kardel 	int	sw, arg, nsec;
   1762          1.1  kardel 
   1763          1.1  kardel 	pp = peer->procptr;
   1764  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   1765          1.1  kardel 	if (!iniflg) {
   1766          1.1  kardel 		iniflg = 1;
   1767  1.1.1.1.6.1    yamt 		ZERO(bitvec);
   1768          1.1  kardel 	}
   1769          1.1  kardel 
   1770          1.1  kardel 	/*
   1771          1.1  kardel 	 * The bit represents the probability of a hit on zero (negative
   1772          1.1  kardel 	 * values), a hit on one (positive values) or a miss (zero
   1773          1.1  kardel 	 * value). The likelihood vector is the exponential average of
   1774          1.1  kardel 	 * these probabilities. Only the bits of this vector
   1775          1.1  kardel 	 * corresponding to the miscellaneous bits of the timecode are
   1776          1.1  kardel 	 * used, but it's easier to do them all. After that, crank the
   1777          1.1  kardel 	 * seconds state machine.
   1778          1.1  kardel 	 */
   1779          1.1  kardel 	nsec = up->rsec;
   1780          1.1  kardel 	up->rsec++;
   1781          1.1  kardel 	bitvec[nsec] += (bit - bitvec[nsec]) / TCONST;
   1782          1.1  kardel 	sw = progx[nsec].sw;
   1783          1.1  kardel 	arg = progx[nsec].arg;
   1784          1.1  kardel 
   1785          1.1  kardel 	/*
   1786          1.1  kardel 	 * The minute state machine. Fly off to a particular section as
   1787          1.1  kardel 	 * directed by the transition matrix and second number.
   1788          1.1  kardel 	 */
   1789          1.1  kardel 	switch (sw) {
   1790          1.1  kardel 
   1791          1.1  kardel 	/*
   1792          1.1  kardel 	 * Ignore this second.
   1793          1.1  kardel 	 */
   1794          1.1  kardel 	case IDLE:			/* 9, 45-49 */
   1795          1.1  kardel 		break;
   1796          1.1  kardel 
   1797          1.1  kardel 	/*
   1798          1.1  kardel 	 * Probe channel stuff
   1799          1.1  kardel 	 *
   1800          1.1  kardel 	 * The WWV/H format contains data pulses in second 59 (position
   1801          1.1  kardel 	 * identifier) and second 1, but not in second 0. The minute
   1802          1.1  kardel 	 * sync pulse is contained in second 0. At the end of second 58
   1803          1.1  kardel 	 * QSY to the probe channel, which rotates in turn over all
   1804          1.1  kardel 	 * WWV/H frequencies. At the end of second 0 measure the minute
   1805          1.1  kardel 	 * sync pulse. At the end of second 1 measure the data pulse and
   1806          1.1  kardel 	 * QSY back to the data channel. Note that the actions commented
   1807          1.1  kardel 	 * here happen at the end of the second numbered as shown.
   1808          1.1  kardel 	 *
   1809          1.1  kardel 	 * At the end of second 0 save the minute sync amplitude latched
   1810          1.1  kardel 	 * at 800 ms as the signal later used to calculate the SNR.
   1811          1.1  kardel 	 */
   1812          1.1  kardel 	case SYNC2:			/* 0 */
   1813          1.1  kardel 		cp = &up->mitig[up->achan];
   1814          1.1  kardel 		cp->wwv.synmax = cp->wwv.syneng;
   1815          1.1  kardel 		cp->wwvh.synmax = cp->wwvh.syneng;
   1816          1.1  kardel 		break;
   1817          1.1  kardel 
   1818          1.1  kardel 	/*
   1819          1.1  kardel 	 * At the end of second 1 use the minute sync amplitude latched
   1820          1.1  kardel 	 * at 800 ms as the noise to calculate the SNR. If the minute
   1821          1.1  kardel 	 * sync pulse and SNR are above thresholds and the data pulse
   1822          1.1  kardel 	 * amplitude and SNR are above thresolds, shift a 1 into the
   1823          1.1  kardel 	 * station reachability register; otherwise, shift a 0. The
   1824          1.1  kardel 	 * number of 1 bits in the last six intervals is a component of
   1825          1.1  kardel 	 * the channel metric computed by the wwv_metric() routine.
   1826          1.1  kardel 	 * Finally, QSY back to the data channel.
   1827          1.1  kardel 	 */
   1828          1.1  kardel 	case SYNC3:			/* 1 */
   1829          1.1  kardel 		cp = &up->mitig[up->achan];
   1830          1.1  kardel 
   1831          1.1  kardel 		/*
   1832          1.1  kardel 		 * WWV station
   1833          1.1  kardel 		 */
   1834          1.1  kardel 		sp = &cp->wwv;
   1835          1.1  kardel 		sp->synsnr = wwv_snr(sp->synmax, sp->amp);
   1836          1.1  kardel 		sp->reach <<= 1;
   1837          1.1  kardel 		if (sp->reach & (1 << AMAX))
   1838          1.1  kardel 			sp->count--;
   1839          1.1  kardel 		if (sp->synmax >= QTHR && sp->synsnr >= QSNR &&
   1840          1.1  kardel 		    !(up->status & (DGATE | BGATE))) {
   1841          1.1  kardel 			sp->reach |= 1;
   1842          1.1  kardel 			sp->count++;
   1843          1.1  kardel 		}
   1844          1.1  kardel 		sp->metric = wwv_metric(sp);
   1845          1.1  kardel 
   1846          1.1  kardel 		/*
   1847          1.1  kardel 		 * WWVH station
   1848          1.1  kardel 		 */
   1849          1.1  kardel 		rp = &cp->wwvh;
   1850          1.1  kardel 		rp->synsnr = wwv_snr(rp->synmax, rp->amp);
   1851          1.1  kardel 		rp->reach <<= 1;
   1852          1.1  kardel 		if (rp->reach & (1 << AMAX))
   1853          1.1  kardel 			rp->count--;
   1854          1.1  kardel 		if (rp->synmax >= QTHR && rp->synsnr >= QSNR &&
   1855          1.1  kardel 		    !(up->status & (DGATE | BGATE))) {
   1856          1.1  kardel 			rp->reach |= 1;
   1857          1.1  kardel 			rp->count++;
   1858          1.1  kardel 		}
   1859          1.1  kardel 		rp->metric = wwv_metric(rp);
   1860          1.1  kardel 		if (pp->sloppyclockflag & CLK_FLAG4) {
   1861  1.1.1.1.6.1    yamt 			snprintf(tbuf, sizeof(tbuf),
   1862          1.1  kardel 			    "wwv5 %04x %3d %4d %.0f/%.1f %.0f/%.1f %s %04x %.0f %.0f/%.1f %s %04x %.0f %.0f/%.1f",
   1863          1.1  kardel 			    up->status, up->gain, up->yepoch,
   1864          1.1  kardel 			    up->epomax, up->eposnr, up->datsig,
   1865          1.1  kardel 			    up->datsnr,
   1866          1.1  kardel 			    sp->refid, sp->reach & 0xffff,
   1867          1.1  kardel 			    sp->metric, sp->synmax, sp->synsnr,
   1868          1.1  kardel 			    rp->refid, rp->reach & 0xffff,
   1869          1.1  kardel 			    rp->metric, rp->synmax, rp->synsnr);
   1870          1.1  kardel 			record_clock_stats(&peer->srcadr, tbuf);
   1871          1.1  kardel #ifdef DEBUG
   1872          1.1  kardel 			if (debug)
   1873          1.1  kardel 				printf("%s\n", tbuf);
   1874          1.1  kardel #endif /* DEBUG */
   1875          1.1  kardel 		}
   1876          1.1  kardel 		up->errcnt = up->digcnt = up->alarm = 0;
   1877          1.1  kardel 
   1878          1.1  kardel 		/*
   1879          1.1  kardel 		 * If synchronized to a station, restart if no stations
   1880          1.1  kardel 		 * have been heard within the PANIC timeout (2 days). If
   1881          1.1  kardel 		 * not and the minute digit has been found, restart if
   1882          1.1  kardel 		 * not synchronized withing the SYNCH timeout (40 m). If
   1883          1.1  kardel 		 * not, restart if the unit digit has not been found
   1884          1.1  kardel 		 * within the DATA timeout (15 m).
   1885          1.1  kardel 		 */
   1886          1.1  kardel 		if (up->status & INSYNC) {
   1887          1.1  kardel 			if (up->watch > PANIC) {
   1888          1.1  kardel 				wwv_newgame(peer);
   1889          1.1  kardel 				return;
   1890          1.1  kardel 			}
   1891          1.1  kardel 		} else if (up->status & DSYNC) {
   1892          1.1  kardel 			if (up->watch > SYNCH) {
   1893          1.1  kardel 				wwv_newgame(peer);
   1894          1.1  kardel 				return;
   1895          1.1  kardel 			}
   1896          1.1  kardel 		} else if (up->watch > DATA) {
   1897          1.1  kardel 			wwv_newgame(peer);
   1898          1.1  kardel 			return;
   1899          1.1  kardel 		}
   1900          1.1  kardel 		wwv_newchan(peer);
   1901          1.1  kardel 		break;
   1902          1.1  kardel 
   1903          1.1  kardel 	/*
   1904          1.1  kardel 	 * Save the bit probability in the BCD data vector at the index
   1905          1.1  kardel 	 * given by the argument. Bits not used in the digit are forced
   1906          1.1  kardel 	 * to zero.
   1907          1.1  kardel 	 */
   1908          1.1  kardel 	case COEF1:			/* 4-7 */
   1909          1.1  kardel 		bcddld[arg] = bit;
   1910          1.1  kardel 		break;
   1911          1.1  kardel 
   1912          1.1  kardel 	case COEF:			/* 10-13, 15-17, 20-23, 25-26,
   1913          1.1  kardel 					   30-33, 35-38, 40-41, 51-54 */
   1914          1.1  kardel 		if (up->status & DSYNC)
   1915          1.1  kardel 			bcddld[arg] = bit;
   1916          1.1  kardel 		else
   1917          1.1  kardel 			bcddld[arg] = 0;
   1918          1.1  kardel 		break;
   1919          1.1  kardel 
   1920          1.1  kardel 	case COEF2:			/* 18, 27-28, 42-43 */
   1921          1.1  kardel 		bcddld[arg] = 0;
   1922          1.1  kardel 		break;
   1923          1.1  kardel 
   1924          1.1  kardel 	/*
   1925          1.1  kardel 	 * Correlate coefficient vector with each valid digit vector and
   1926          1.1  kardel 	 * save in decoding matrix. We step through the decoding matrix
   1927          1.1  kardel 	 * digits correlating each with the coefficients and saving the
   1928          1.1  kardel 	 * greatest and the next lower for later SNR calculation.
   1929          1.1  kardel 	 */
   1930          1.1  kardel 	case DECIM2:			/* 29 */
   1931          1.1  kardel 		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2);
   1932          1.1  kardel 		break;
   1933          1.1  kardel 
   1934          1.1  kardel 	case DECIM3:			/* 44 */
   1935          1.1  kardel 		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3);
   1936          1.1  kardel 		break;
   1937          1.1  kardel 
   1938          1.1  kardel 	case DECIM6:			/* 19 */
   1939          1.1  kardel 		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6);
   1940          1.1  kardel 		break;
   1941          1.1  kardel 
   1942          1.1  kardel 	case DECIM9:			/* 8, 14, 24, 34, 39 */
   1943          1.1  kardel 		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9);
   1944          1.1  kardel 		break;
   1945          1.1  kardel 
   1946          1.1  kardel 	/*
   1947          1.1  kardel 	 * Miscellaneous bits. If above the positive threshold, declare
   1948          1.1  kardel 	 * 1; if below the negative threshold, declare 0; otherwise
   1949          1.1  kardel 	 * raise the BGATE bit. The design is intended to avoid
   1950          1.1  kardel 	 * integrating noise under low SNR conditions.
   1951          1.1  kardel 	 */
   1952          1.1  kardel 	case MSC20:			/* 55 */
   1953          1.1  kardel 		wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);
   1954          1.1  kardel 		/* fall through */
   1955          1.1  kardel 
   1956          1.1  kardel 	case MSCBIT:			/* 2-3, 50, 56-57 */
   1957          1.1  kardel 		if (bitvec[nsec] > BTHR) {
   1958          1.1  kardel 			if (!(up->misc & arg))
   1959          1.1  kardel 				up->alarm |= CMPERR;
   1960          1.1  kardel 			up->misc |= arg;
   1961          1.1  kardel 		} else if (bitvec[nsec] < -BTHR) {
   1962          1.1  kardel 			if (up->misc & arg)
   1963          1.1  kardel 				up->alarm |= CMPERR;
   1964          1.1  kardel 			up->misc &= ~arg;
   1965          1.1  kardel 		} else {
   1966          1.1  kardel 			up->status |= BGATE;
   1967          1.1  kardel 		}
   1968          1.1  kardel 		break;
   1969          1.1  kardel 
   1970          1.1  kardel 	/*
   1971          1.1  kardel 	 * Save the data channel gain, then QSY to the probe channel and
   1972          1.1  kardel 	 * dim the seconds comb filters. The www_newchan() routine will
   1973          1.1  kardel 	 * light them back up.
   1974          1.1  kardel 	 */
   1975          1.1  kardel 	case MSC21:			/* 58 */
   1976          1.1  kardel 		if (bitvec[nsec] > BTHR) {
   1977          1.1  kardel 			if (!(up->misc & arg))
   1978          1.1  kardel 				up->alarm |= CMPERR;
   1979          1.1  kardel 			up->misc |= arg;
   1980          1.1  kardel 		} else if (bitvec[nsec] < -BTHR) {
   1981          1.1  kardel 			if (up->misc & arg)
   1982          1.1  kardel 				up->alarm |= CMPERR;
   1983          1.1  kardel 			up->misc &= ~arg;
   1984          1.1  kardel 		} else {
   1985          1.1  kardel 			up->status |= BGATE;
   1986          1.1  kardel 		}
   1987          1.1  kardel 		up->status &= ~(SELV | SELH);
   1988          1.1  kardel #ifdef ICOM
   1989          1.1  kardel 		if (up->fd_icom > 0) {
   1990          1.1  kardel 			up->schan = (up->schan + 1) % NCHAN;
   1991          1.1  kardel 			wwv_qsy(peer, up->schan);
   1992          1.1  kardel 		} else {
   1993          1.1  kardel 			up->mitig[up->achan].gain = up->gain;
   1994          1.1  kardel 		}
   1995          1.1  kardel #else
   1996          1.1  kardel 		up->mitig[up->achan].gain = up->gain;
   1997          1.1  kardel #endif /* ICOM */
   1998          1.1  kardel 		break;
   1999          1.1  kardel 
   2000          1.1  kardel 	/*
   2001          1.1  kardel 	 * The endgames
   2002          1.1  kardel 	 *
   2003          1.1  kardel 	 * During second 59 the receiver and codec AGC are settling
   2004          1.1  kardel 	 * down, so the data pulse is unusable as quality metric. If
   2005          1.1  kardel 	 * LEPSEC is set on the last minute of 30 June or 31 December,
   2006          1.1  kardel 	 * the transmitter and receiver insert an extra second (60) in
   2007          1.1  kardel 	 * the timescale and the minute sync repeats the second. Once
   2008          1.1  kardel 	 * leaps occurred at intervals of about 18 months, but the last
   2009          1.1  kardel 	 * leap before the most recent leap in 1995 was in  1998.
   2010          1.1  kardel 	 */
   2011          1.1  kardel 	case MIN1:			/* 59 */
   2012          1.1  kardel 		if (up->status & LEPSEC)
   2013          1.1  kardel 			break;
   2014          1.1  kardel 
   2015          1.1  kardel 		/* fall through */
   2016          1.1  kardel 
   2017          1.1  kardel 	case MIN2:			/* 60 */
   2018          1.1  kardel 		up->status &= ~LEPSEC;
   2019          1.1  kardel 		wwv_tsec(peer);
   2020          1.1  kardel 		up->rsec = 0;
   2021          1.1  kardel 		wwv_clock(peer);
   2022          1.1  kardel 		break;
   2023          1.1  kardel 	}
   2024          1.1  kardel 	if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
   2025          1.1  kardel 	    DSYNC)) {
   2026  1.1.1.1.6.1    yamt 		snprintf(tbuf, sizeof(tbuf),
   2027          1.1  kardel 		    "wwv3 %2d %04x %3d %4d %5.0f %5.1f %5.0f %5.1f %5.0f",
   2028          1.1  kardel 		    nsec, up->status, up->gain, up->yepoch, up->epomax,
   2029          1.1  kardel 		    up->eposnr, up->datsig, up->datsnr, bit);
   2030          1.1  kardel 		record_clock_stats(&peer->srcadr, tbuf);
   2031          1.1  kardel #ifdef DEBUG
   2032          1.1  kardel 		if (debug)
   2033          1.1  kardel 			printf("%s\n", tbuf);
   2034          1.1  kardel #endif /* DEBUG */
   2035          1.1  kardel 	}
   2036          1.1  kardel 	pp->disp += AUDIO_PHI;
   2037          1.1  kardel }
   2038          1.1  kardel 
   2039          1.1  kardel /*
   2040          1.1  kardel  * The radio clock is set if the alarm bits are all zero. After that,
   2041          1.1  kardel  * the time is considered valid if the second sync bit is lit. It should
   2042          1.1  kardel  * not be a surprise, especially if the radio is not tunable, that
   2043          1.1  kardel  * sometimes no stations are above the noise and the integrators
   2044          1.1  kardel  * discharge below the thresholds. We assume that, after a day of signal
   2045          1.1  kardel  * loss, the minute sync epoch will be in the same second. This requires
   2046          1.1  kardel  * the codec frequency be accurate within 6 PPM. Practical experience
   2047          1.1  kardel  * shows the frequency typically within 0.1 PPM, so after a day of
   2048          1.1  kardel  * signal loss, the time should be within 8.6 ms..
   2049          1.1  kardel  */
   2050          1.1  kardel static void
   2051          1.1  kardel wwv_clock(
   2052          1.1  kardel 	struct peer *peer	/* peer unit pointer */
   2053          1.1  kardel 	)
   2054          1.1  kardel {
   2055          1.1  kardel 	struct refclockproc *pp;
   2056          1.1  kardel 	struct wwvunit *up;
   2057          1.1  kardel 	l_fp	offset;		/* offset in NTP seconds */
   2058          1.1  kardel 
   2059          1.1  kardel 	pp = peer->procptr;
   2060  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2061          1.1  kardel 	if (!(up->status & SSYNC))
   2062          1.1  kardel 		up->alarm |= SYNERR;
   2063          1.1  kardel 	if (up->digcnt < 9)
   2064          1.1  kardel 		up->alarm |= NINERR;
   2065          1.1  kardel 	if (!(up->alarm))
   2066          1.1  kardel 		up->status |= INSYNC;
   2067          1.1  kardel 	if (up->status & INSYNC && up->status & SSYNC) {
   2068          1.1  kardel 		if (up->misc & SECWAR)
   2069          1.1  kardel 			pp->leap = LEAP_ADDSECOND;
   2070          1.1  kardel 		else
   2071          1.1  kardel 			pp->leap = LEAP_NOWARNING;
   2072          1.1  kardel 		pp->second = up->rsec;
   2073          1.1  kardel 		pp->minute = up->decvec[MN].digit + up->decvec[MN +
   2074          1.1  kardel 		    1].digit * 10;
   2075          1.1  kardel 		pp->hour = up->decvec[HR].digit + up->decvec[HR +
   2076          1.1  kardel 		    1].digit * 10;
   2077          1.1  kardel 		pp->day = up->decvec[DA].digit + up->decvec[DA +
   2078          1.1  kardel 		    1].digit * 10 + up->decvec[DA + 2].digit * 100;
   2079          1.1  kardel 		pp->year = up->decvec[YR].digit + up->decvec[YR +
   2080          1.1  kardel 		    1].digit * 10;
   2081          1.1  kardel 		pp->year += 2000;
   2082          1.1  kardel 		L_CLR(&offset);
   2083          1.1  kardel 		if (!clocktime(pp->day, pp->hour, pp->minute,
   2084          1.1  kardel 		    pp->second, GMT, up->timestamp.l_ui,
   2085          1.1  kardel 		    &pp->yearstart, &offset.l_ui)) {
   2086          1.1  kardel 			up->errflg = CEVNT_BADTIME;
   2087          1.1  kardel 		} else {
   2088          1.1  kardel 			up->watch = 0;
   2089          1.1  kardel 			pp->disp = 0;
   2090          1.1  kardel 			pp->lastref = up->timestamp;
   2091          1.1  kardel 			refclock_process_offset(pp, offset,
   2092          1.1  kardel 			    up->timestamp, PDELAY + up->pdelay);
   2093          1.1  kardel 			refclock_receive(peer);
   2094          1.1  kardel 		}
   2095          1.1  kardel 	}
   2096  1.1.1.1.6.1    yamt 	pp->lencode = timecode(up, pp->a_lastcode,
   2097  1.1.1.1.6.1    yamt 			       sizeof(pp->a_lastcode));
   2098          1.1  kardel 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
   2099          1.1  kardel #ifdef DEBUG
   2100          1.1  kardel 	if (debug)
   2101          1.1  kardel 		printf("wwv: timecode %d %s\n", pp->lencode,
   2102          1.1  kardel 		    pp->a_lastcode);
   2103          1.1  kardel #endif /* DEBUG */
   2104          1.1  kardel }
   2105          1.1  kardel 
   2106          1.1  kardel 
   2107          1.1  kardel /*
   2108          1.1  kardel  * wwv_corr4 - determine maximum-likelihood digit
   2109          1.1  kardel  *
   2110          1.1  kardel  * This routine correlates the received digit vector with the BCD
   2111          1.1  kardel  * coefficient vectors corresponding to all valid digits at the given
   2112          1.1  kardel  * position in the decoding matrix. The maximum value corresponds to the
   2113          1.1  kardel  * maximum-likelihood digit, while the ratio of this value to the next
   2114          1.1  kardel  * lower value determines the likelihood function. Note that, if the
   2115          1.1  kardel  * digit is invalid, the likelihood vector is averaged toward a miss.
   2116          1.1  kardel  */
   2117          1.1  kardel static void
   2118          1.1  kardel wwv_corr4(
   2119          1.1  kardel 	struct peer *peer,	/* peer unit pointer */
   2120          1.1  kardel 	struct decvec *vp,	/* decoding table pointer */
   2121          1.1  kardel 	double	data[],		/* received data vector */
   2122          1.1  kardel 	double	tab[][4]	/* correlation vector array */
   2123          1.1  kardel 	)
   2124          1.1  kardel {
   2125          1.1  kardel 	struct refclockproc *pp;
   2126          1.1  kardel 	struct wwvunit *up;
   2127          1.1  kardel 	double	topmax, nxtmax;	/* metrics */
   2128          1.1  kardel 	double	acc;		/* accumulator */
   2129          1.1  kardel 	char	tbuf[TBUF];	/* monitor buffer */
   2130          1.1  kardel 	int	mldigit;	/* max likelihood digit */
   2131          1.1  kardel 	int	i, j;
   2132          1.1  kardel 
   2133          1.1  kardel 	pp = peer->procptr;
   2134  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2135          1.1  kardel 
   2136          1.1  kardel 	/*
   2137          1.1  kardel 	 * Correlate digit vector with each BCD coefficient vector. If
   2138          1.1  kardel 	 * any BCD digit bit is bad, consider all bits a miss. Until the
   2139          1.1  kardel 	 * minute units digit has been resolved, don't to anything else.
   2140          1.1  kardel 	 * Note the SNR is calculated as the ratio of the largest
   2141          1.1  kardel 	 * likelihood value to the next largest likelihood value.
   2142          1.1  kardel  	 */
   2143          1.1  kardel 	mldigit = 0;
   2144          1.1  kardel 	topmax = nxtmax = -MAXAMP;
   2145          1.1  kardel 	for (i = 0; tab[i][0] != 0; i++) {
   2146          1.1  kardel 		acc = 0;
   2147          1.1  kardel 		for (j = 0; j < 4; j++)
   2148          1.1  kardel 			acc += data[j] * tab[i][j];
   2149          1.1  kardel 		acc = (vp->like[i] += (acc - vp->like[i]) / TCONST);
   2150          1.1  kardel 		if (acc > topmax) {
   2151          1.1  kardel 			nxtmax = topmax;
   2152          1.1  kardel 			topmax = acc;
   2153          1.1  kardel 			mldigit = i;
   2154          1.1  kardel 		} else if (acc > nxtmax) {
   2155          1.1  kardel 			nxtmax = acc;
   2156          1.1  kardel 		}
   2157          1.1  kardel 	}
   2158          1.1  kardel 	vp->digprb = topmax;
   2159          1.1  kardel 	vp->digsnr = wwv_snr(topmax, nxtmax);
   2160          1.1  kardel 
   2161          1.1  kardel 	/*
   2162          1.1  kardel 	 * The current maximum-likelihood digit is compared to the last
   2163          1.1  kardel 	 * maximum-likelihood digit. If different, the compare counter
   2164          1.1  kardel 	 * and maximum-likelihood digit are reset.  When the compare
   2165          1.1  kardel 	 * counter reaches the BCMP threshold (3), the digit is assumed
   2166          1.1  kardel 	 * correct. When the compare counter of all nine digits have
   2167          1.1  kardel 	 * reached threshold, the clock is assumed correct.
   2168          1.1  kardel 	 *
   2169          1.1  kardel 	 * Note that the clock display digit is set before the compare
   2170          1.1  kardel 	 * counter has reached threshold; however, the clock display is
   2171          1.1  kardel 	 * not considered correct until all nine clock digits have
   2172          1.1  kardel 	 * reached threshold. This is intended as eye candy, but avoids
   2173          1.1  kardel 	 * mistakes when the signal is low and the SNR is very marginal.
   2174          1.1  kardel 	 */
   2175          1.1  kardel 	if (vp->digprb < BTHR || vp->digsnr < BSNR) {
   2176          1.1  kardel 		up->status |= BGATE;
   2177          1.1  kardel 	} else {
   2178          1.1  kardel 		if (vp->digit != mldigit) {
   2179          1.1  kardel 			up->alarm |= CMPERR;
   2180          1.1  kardel 			if (vp->count > 0)
   2181          1.1  kardel 				vp->count--;
   2182          1.1  kardel 			if (vp->count == 0)
   2183          1.1  kardel 				vp->digit = mldigit;
   2184          1.1  kardel 		} else {
   2185          1.1  kardel 			if (vp->count < BCMP)
   2186          1.1  kardel 				vp->count++;
   2187          1.1  kardel 			if (vp->count == BCMP) {
   2188          1.1  kardel 				up->status |= DSYNC;
   2189          1.1  kardel 				up->digcnt++;
   2190          1.1  kardel 			}
   2191          1.1  kardel 		}
   2192          1.1  kardel 	}
   2193          1.1  kardel 	if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
   2194          1.1  kardel 	    INSYNC)) {
   2195  1.1.1.1.6.1    yamt 		snprintf(tbuf, sizeof(tbuf),
   2196          1.1  kardel 		    "wwv4 %2d %04x %3d %4d %5.0f %2d %d %d %d %5.0f %5.1f",
   2197          1.1  kardel 		    up->rsec - 1, up->status, up->gain, up->yepoch,
   2198          1.1  kardel 		    up->epomax, vp->radix, vp->digit, mldigit,
   2199          1.1  kardel 		    vp->count, vp->digprb, vp->digsnr);
   2200          1.1  kardel 		record_clock_stats(&peer->srcadr, tbuf);
   2201          1.1  kardel #ifdef DEBUG
   2202          1.1  kardel 		if (debug)
   2203          1.1  kardel 			printf("%s\n", tbuf);
   2204          1.1  kardel #endif /* DEBUG */
   2205          1.1  kardel 	}
   2206          1.1  kardel }
   2207          1.1  kardel 
   2208          1.1  kardel 
   2209          1.1  kardel /*
   2210          1.1  kardel  * wwv_tsec - transmitter minute processing
   2211          1.1  kardel  *
   2212          1.1  kardel  * This routine is called at the end of the transmitter minute. It
   2213          1.1  kardel  * implements a state machine that advances the logical clock subject to
   2214          1.1  kardel  * the funny rules that govern the conventional clock and calendar.
   2215          1.1  kardel  */
   2216          1.1  kardel static void
   2217          1.1  kardel wwv_tsec(
   2218          1.1  kardel 	struct peer *peer	/* driver structure pointer */
   2219          1.1  kardel 	)
   2220          1.1  kardel {
   2221          1.1  kardel 	struct refclockproc *pp;
   2222          1.1  kardel 	struct wwvunit *up;
   2223          1.1  kardel 	int minute, day, isleap;
   2224          1.1  kardel 	int temp;
   2225          1.1  kardel 
   2226          1.1  kardel 	pp = peer->procptr;
   2227  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2228          1.1  kardel 
   2229          1.1  kardel 	/*
   2230          1.1  kardel 	 * Advance minute unit of the day. Don't propagate carries until
   2231          1.1  kardel 	 * the unit minute digit has been found.
   2232          1.1  kardel 	 */
   2233          1.1  kardel 	temp = carry(&up->decvec[MN]);	/* minute units */
   2234          1.1  kardel 	if (!(up->status & DSYNC))
   2235          1.1  kardel 		return;
   2236          1.1  kardel 
   2237          1.1  kardel 	/*
   2238          1.1  kardel 	 * Propagate carries through the day.
   2239          1.1  kardel 	 */
   2240          1.1  kardel 	if (temp == 0)			/* carry minutes */
   2241          1.1  kardel 		temp = carry(&up->decvec[MN + 1]);
   2242          1.1  kardel 	if (temp == 0)			/* carry hours */
   2243          1.1  kardel 		temp = carry(&up->decvec[HR]);
   2244          1.1  kardel 	if (temp == 0)
   2245          1.1  kardel 		temp = carry(&up->decvec[HR + 1]);
   2246          1.1  kardel 
   2247          1.1  kardel 	/*
   2248          1.1  kardel 	 * Decode the current minute and day. Set leap day if the
   2249          1.1  kardel 	 * timecode leap bit is set on 30 June or 31 December. Set leap
   2250          1.1  kardel 	 * minute if the last minute on leap day, but only if the clock
   2251          1.1  kardel 	 * is syncrhronized. This code fails in 2400 AD.
   2252          1.1  kardel 	 */
   2253          1.1  kardel 	minute = up->decvec[MN].digit + up->decvec[MN + 1].digit *
   2254          1.1  kardel 	    10 + up->decvec[HR].digit * 60 + up->decvec[HR +
   2255          1.1  kardel 	    1].digit * 600;
   2256          1.1  kardel 	day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
   2257          1.1  kardel 	    up->decvec[DA + 2].digit * 100;
   2258          1.1  kardel 
   2259          1.1  kardel 	/*
   2260          1.1  kardel 	 * Set the leap bit on the last minute of the leap day.
   2261          1.1  kardel 	 */
   2262          1.1  kardel 	isleap = up->decvec[YR].digit & 0x3;
   2263          1.1  kardel 	if (up->misc & SECWAR && up->status & INSYNC) {
   2264          1.1  kardel 		if ((day == (isleap ? 182 : 183) || day == (isleap ?
   2265          1.1  kardel 		    365 : 366)) && minute == 1439)
   2266          1.1  kardel 			up->status |= LEPSEC;
   2267          1.1  kardel 	}
   2268          1.1  kardel 
   2269          1.1  kardel 	/*
   2270          1.1  kardel 	 * Roll the day if this the first minute and propagate carries
   2271          1.1  kardel 	 * through the year.
   2272          1.1  kardel 	 */
   2273          1.1  kardel 	if (minute != 1440)
   2274          1.1  kardel 		return;
   2275          1.1  kardel 
   2276          1.1  kardel 	minute = 0;
   2277          1.1  kardel 	while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */
   2278          1.1  kardel 	while (carry(&up->decvec[HR + 1]) != 0);
   2279          1.1  kardel 	day++;
   2280          1.1  kardel 	temp = carry(&up->decvec[DA]);	/* carry days */
   2281          1.1  kardel 	if (temp == 0)
   2282          1.1  kardel 		temp = carry(&up->decvec[DA + 1]);
   2283          1.1  kardel 	if (temp == 0)
   2284          1.1  kardel 		temp = carry(&up->decvec[DA + 2]);
   2285          1.1  kardel 
   2286          1.1  kardel 	/*
   2287          1.1  kardel 	 * Roll the year if this the first day and propagate carries
   2288          1.1  kardel 	 * through the century.
   2289          1.1  kardel 	 */
   2290          1.1  kardel 	if (day != (isleap ? 365 : 366))
   2291          1.1  kardel 		return;
   2292          1.1  kardel 
   2293          1.1  kardel 	day = 1;
   2294          1.1  kardel 	while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */
   2295          1.1  kardel 	while (carry(&up->decvec[DA + 1]) != 0);
   2296          1.1  kardel 	while (carry(&up->decvec[DA + 2]) != 0);
   2297          1.1  kardel 	temp = carry(&up->decvec[YR]);	/* carry years */
   2298          1.1  kardel 	if (temp == 0)
   2299          1.1  kardel 		carry(&up->decvec[YR + 1]);
   2300          1.1  kardel }
   2301          1.1  kardel 
   2302          1.1  kardel 
   2303          1.1  kardel /*
   2304          1.1  kardel  * carry - process digit
   2305          1.1  kardel  *
   2306          1.1  kardel  * This routine rotates a likelihood vector one position and increments
   2307          1.1  kardel  * the clock digit modulo the radix. It returns the new clock digit or
   2308          1.1  kardel  * zero if a carry occurred. Once synchronized, the clock digit will
   2309          1.1  kardel  * match the maximum-likelihood digit corresponding to that position.
   2310          1.1  kardel  */
   2311          1.1  kardel static int
   2312          1.1  kardel carry(
   2313          1.1  kardel 	struct decvec *dp	/* decoding table pointer */
   2314          1.1  kardel 	)
   2315          1.1  kardel {
   2316          1.1  kardel 	int temp;
   2317          1.1  kardel 	int j;
   2318          1.1  kardel 
   2319          1.1  kardel 	dp->digit++;
   2320          1.1  kardel 	if (dp->digit == dp->radix)
   2321          1.1  kardel 		dp->digit = 0;
   2322          1.1  kardel 	temp = dp->like[dp->radix - 1];
   2323          1.1  kardel 	for (j = dp->radix - 1; j > 0; j--)
   2324          1.1  kardel 		dp->like[j] = dp->like[j - 1];
   2325          1.1  kardel 	dp->like[0] = temp;
   2326          1.1  kardel 	return (dp->digit);
   2327          1.1  kardel }
   2328          1.1  kardel 
   2329          1.1  kardel 
   2330          1.1  kardel /*
   2331          1.1  kardel  * wwv_snr - compute SNR or likelihood function
   2332          1.1  kardel  */
   2333          1.1  kardel static double
   2334          1.1  kardel wwv_snr(
   2335          1.1  kardel 	double signal,		/* signal */
   2336          1.1  kardel 	double noise		/* noise */
   2337          1.1  kardel 	)
   2338          1.1  kardel {
   2339          1.1  kardel 	double rval;
   2340          1.1  kardel 
   2341          1.1  kardel 	/*
   2342          1.1  kardel 	 * This is a little tricky. Due to the way things are measured,
   2343          1.1  kardel 	 * either or both the signal or noise amplitude can be negative
   2344          1.1  kardel 	 * or zero. The intent is that, if the signal is negative or
   2345          1.1  kardel 	 * zero, the SNR must always be zero. This can happen with the
   2346          1.1  kardel 	 * subcarrier SNR before the phase has been aligned. On the
   2347          1.1  kardel 	 * other hand, in the likelihood function the "noise" is the
   2348          1.1  kardel 	 * next maximum down from the peak and this could be negative.
   2349          1.1  kardel 	 * However, in this case the SNR is truly stupendous, so we
   2350          1.1  kardel 	 * simply cap at MAXSNR dB (40).
   2351          1.1  kardel 	 */
   2352          1.1  kardel 	if (signal <= 0) {
   2353          1.1  kardel 		rval = 0;
   2354          1.1  kardel 	} else if (noise <= 0) {
   2355          1.1  kardel 		rval = MAXSNR;
   2356          1.1  kardel 	} else {
   2357          1.1  kardel 		rval = 20. * log10(signal / noise);
   2358          1.1  kardel 		if (rval > MAXSNR)
   2359          1.1  kardel 			rval = MAXSNR;
   2360          1.1  kardel 	}
   2361          1.1  kardel 	return (rval);
   2362          1.1  kardel }
   2363          1.1  kardel 
   2364          1.1  kardel 
   2365          1.1  kardel /*
   2366          1.1  kardel  * wwv_newchan - change to new data channel
   2367          1.1  kardel  *
   2368          1.1  kardel  * The radio actually appears to have ten channels, one channel for each
   2369          1.1  kardel  * of five frequencies and each of two stations (WWV and WWVH), although
   2370          1.1  kardel  * if not tunable only the DCHAN channel appears live. While the radio
   2371          1.1  kardel  * is tuned to the working data channel frequency and station for most
   2372          1.1  kardel  * of the minute, during seconds 59, 0 and 1 the radio is tuned to a
   2373          1.1  kardel  * probe frequency in order to search for minute sync pulse and data
   2374          1.1  kardel  * subcarrier from other transmitters.
   2375          1.1  kardel  *
   2376          1.1  kardel  * The search for WWV and WWVH operates simultaneously, with WWV minute
   2377          1.1  kardel  * sync pulse at 1000 Hz and WWVH at 1200 Hz. The probe frequency
   2378          1.1  kardel  * rotates each minute over 2.5, 5, 10, 15 and 20 MHz in order and yes,
   2379          1.1  kardel  * we all know WWVH is dark on 20 MHz, but few remember when WWV was lit
   2380          1.1  kardel  * on 25 MHz.
   2381          1.1  kardel  *
   2382          1.1  kardel  * This routine selects the best channel using a metric computed from
   2383          1.1  kardel  * the reachability register and minute pulse amplitude. Normally, the
   2384          1.1  kardel  * award goes to the the channel with the highest metric; but, in case
   2385          1.1  kardel  * of ties, the award goes to the channel with the highest minute sync
   2386          1.1  kardel  * pulse amplitude and then to the highest frequency.
   2387          1.1  kardel  *
   2388          1.1  kardel  * The routine performs an important squelch function to keep dirty data
   2389          1.1  kardel  * from polluting the integrators. In order to consider a station valid,
   2390          1.1  kardel  * the metric must be at least MTHR (13); otherwise, the station select
   2391          1.1  kardel  * bits are cleared so the second sync is disabled and the data bit
   2392          1.1  kardel  * integrators averaged to a miss.
   2393          1.1  kardel  */
   2394          1.1  kardel static int
   2395          1.1  kardel wwv_newchan(
   2396          1.1  kardel 	struct peer *peer	/* peer structure pointer */
   2397          1.1  kardel 	)
   2398          1.1  kardel {
   2399          1.1  kardel 	struct refclockproc *pp;
   2400          1.1  kardel 	struct wwvunit *up;
   2401          1.1  kardel 	struct sync *sp, *rp;
   2402          1.1  kardel 	double rank, dtemp;
   2403          1.1  kardel 	int i, j, rval;
   2404          1.1  kardel 
   2405          1.1  kardel 	pp = peer->procptr;
   2406  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2407          1.1  kardel 
   2408          1.1  kardel 	/*
   2409          1.1  kardel 	 * Search all five station pairs looking for the channel with
   2410          1.1  kardel 	 * maximum metric.
   2411          1.1  kardel 	 */
   2412          1.1  kardel 	sp = NULL;
   2413          1.1  kardel 	j = 0;
   2414          1.1  kardel 	rank = 0;
   2415          1.1  kardel 	for (i = 0; i < NCHAN; i++) {
   2416          1.1  kardel 		rp = &up->mitig[i].wwvh;
   2417          1.1  kardel 		dtemp = rp->metric;
   2418          1.1  kardel 		if (dtemp >= rank) {
   2419          1.1  kardel 			rank = dtemp;
   2420          1.1  kardel 			sp = rp;
   2421          1.1  kardel 			j = i;
   2422          1.1  kardel 		}
   2423          1.1  kardel 		rp = &up->mitig[i].wwv;
   2424          1.1  kardel 		dtemp = rp->metric;
   2425          1.1  kardel 		if (dtemp >= rank) {
   2426          1.1  kardel 			rank = dtemp;
   2427          1.1  kardel 			sp = rp;
   2428          1.1  kardel 			j = i;
   2429          1.1  kardel 		}
   2430          1.1  kardel 	}
   2431          1.1  kardel 
   2432          1.1  kardel 	/*
   2433          1.1  kardel 	 * If the strongest signal is less than the MTHR threshold (13),
   2434          1.1  kardel 	 * we are beneath the waves, so squelch the second sync and
   2435          1.1  kardel 	 * advance to the next station. This makes sure all stations are
   2436          1.1  kardel 	 * scanned when the ions grow dim. If the strongest signal is
   2437          1.1  kardel 	 * greater than the threshold, tune to that frequency and
   2438          1.1  kardel 	 * transmitter QTH.
   2439          1.1  kardel 	 */
   2440          1.1  kardel 	up->status &= ~(SELV | SELH);
   2441          1.1  kardel 	if (rank < MTHR) {
   2442          1.1  kardel 		up->dchan = (up->dchan + 1) % NCHAN;
   2443          1.1  kardel 		if (up->status & METRIC) {
   2444          1.1  kardel 			up->status &= ~METRIC;
   2445          1.1  kardel 			refclock_report(peer, CEVNT_PROP);
   2446          1.1  kardel 		}
   2447          1.1  kardel 		rval = FALSE;
   2448          1.1  kardel 	} else {
   2449          1.1  kardel 		up->dchan = j;
   2450          1.1  kardel 		up->sptr = sp;
   2451          1.1  kardel 		memcpy(&pp->refid, sp->refid, 4);
   2452          1.1  kardel 		peer->refid = pp->refid;
   2453          1.1  kardel 		up->status |= METRIC;
   2454          1.1  kardel 		if (sp->select & SELV) {
   2455          1.1  kardel 			up->status |= SELV;
   2456          1.1  kardel 			up->pdelay = pp->fudgetime1;
   2457          1.1  kardel 		} else if (sp->select & SELH) {
   2458          1.1  kardel 			up->status |= SELH;
   2459          1.1  kardel 			up->pdelay = pp->fudgetime2;
   2460          1.1  kardel 		} else {
   2461          1.1  kardel 			up->pdelay = 0;
   2462          1.1  kardel 		}
   2463          1.1  kardel 		rval = TRUE;
   2464          1.1  kardel 	}
   2465          1.1  kardel #ifdef ICOM
   2466          1.1  kardel 	if (up->fd_icom > 0)
   2467          1.1  kardel 		wwv_qsy(peer, up->dchan);
   2468          1.1  kardel #endif /* ICOM */
   2469          1.1  kardel 	return (rval);
   2470          1.1  kardel }
   2471          1.1  kardel 
   2472          1.1  kardel 
   2473          1.1  kardel /*
   2474          1.1  kardel  * wwv_newgame - reset and start over
   2475          1.1  kardel  *
   2476          1.1  kardel  * There are three conditions resulting in a new game:
   2477          1.1  kardel  *
   2478          1.1  kardel  * 1	After finding the minute pulse (MSYNC lit), going 15 minutes
   2479          1.1  kardel  *	(DATA) without finding the unit seconds digit.
   2480          1.1  kardel  *
   2481          1.1  kardel  * 2	After finding good data (DSYNC lit), going more than 40 minutes
   2482          1.1  kardel  *	(SYNCH) without finding station sync (INSYNC lit).
   2483          1.1  kardel  *
   2484          1.1  kardel  * 3	After finding station sync (INSYNC lit), going more than 2 days
   2485          1.1  kardel  *	(PANIC) without finding any station.
   2486          1.1  kardel  */
   2487          1.1  kardel static void
   2488          1.1  kardel wwv_newgame(
   2489          1.1  kardel 	struct peer *peer	/* peer structure pointer */
   2490          1.1  kardel 	)
   2491          1.1  kardel {
   2492          1.1  kardel 	struct refclockproc *pp;
   2493          1.1  kardel 	struct wwvunit *up;
   2494          1.1  kardel 	struct chan *cp;
   2495          1.1  kardel 	int i;
   2496          1.1  kardel 
   2497          1.1  kardel 	pp = peer->procptr;
   2498  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2499          1.1  kardel 
   2500          1.1  kardel 	/*
   2501          1.1  kardel 	 * Initialize strategic values. Note we set the leap bits
   2502          1.1  kardel 	 * NOTINSYNC and the refid "NONE".
   2503          1.1  kardel 	 */
   2504          1.1  kardel 	if (up->status)
   2505          1.1  kardel 		up->errflg = CEVNT_TIMEOUT;
   2506          1.1  kardel 	peer->leap = LEAP_NOTINSYNC;
   2507          1.1  kardel 	up->watch = up->status = up->alarm = 0;
   2508          1.1  kardel 	up->avgint = MINAVG;
   2509          1.1  kardel 	up->freq = 0;
   2510          1.1  kardel 	up->gain = MAXGAIN / 2;
   2511          1.1  kardel 
   2512          1.1  kardel 	/*
   2513          1.1  kardel 	 * Initialize the station processes for audio gain, select bit,
   2514          1.1  kardel 	 * station/frequency identifier and reference identifier. Start
   2515          1.1  kardel 	 * probing at the strongest channel or the default channel if
   2516          1.1  kardel 	 * nothing heard.
   2517          1.1  kardel 	 */
   2518          1.1  kardel 	memset(up->mitig, 0, sizeof(up->mitig));
   2519          1.1  kardel 	for (i = 0; i < NCHAN; i++) {
   2520          1.1  kardel 		cp = &up->mitig[i];
   2521          1.1  kardel 		cp->gain = up->gain;
   2522          1.1  kardel 		cp->wwv.select = SELV;
   2523  1.1.1.1.6.1    yamt 		snprintf(cp->wwv.refid, sizeof(cp->wwv.refid), "WV%.0f",
   2524  1.1.1.1.6.1    yamt 		    floor(qsy[i]));
   2525          1.1  kardel 		cp->wwvh.select = SELH;
   2526  1.1.1.1.6.1    yamt 		snprintf(cp->wwvh.refid, sizeof(cp->wwvh.refid), "WH%.0f",
   2527  1.1.1.1.6.1    yamt 		    floor(qsy[i]));
   2528          1.1  kardel 	}
   2529          1.1  kardel 	up->dchan = (DCHAN + NCHAN - 1) % NCHAN;
   2530          1.1  kardel 	wwv_newchan(peer);
   2531          1.1  kardel 	up->schan = up->dchan;
   2532          1.1  kardel }
   2533          1.1  kardel 
   2534          1.1  kardel /*
   2535          1.1  kardel  * wwv_metric - compute station metric
   2536          1.1  kardel  *
   2537          1.1  kardel  * The most significant bits represent the number of ones in the
   2538          1.1  kardel  * station reachability register. The least significant bits represent
   2539          1.1  kardel  * the minute sync pulse amplitude. The combined value is scaled 0-100.
   2540          1.1  kardel  */
   2541          1.1  kardel double
   2542          1.1  kardel wwv_metric(
   2543          1.1  kardel 	struct sync *sp		/* station pointer */
   2544          1.1  kardel 	)
   2545          1.1  kardel {
   2546          1.1  kardel 	double	dtemp;
   2547          1.1  kardel 
   2548          1.1  kardel 	dtemp = sp->count * MAXAMP;
   2549          1.1  kardel 	if (sp->synmax < MAXAMP)
   2550          1.1  kardel 		dtemp += sp->synmax;
   2551          1.1  kardel 	else
   2552          1.1  kardel 		dtemp += MAXAMP - 1;
   2553          1.1  kardel 	dtemp /= (AMAX + 1) * MAXAMP;
   2554          1.1  kardel 	return (dtemp * 100.);
   2555          1.1  kardel }
   2556          1.1  kardel 
   2557          1.1  kardel 
   2558          1.1  kardel #ifdef ICOM
   2559          1.1  kardel /*
   2560          1.1  kardel  * wwv_qsy - Tune ICOM receiver
   2561          1.1  kardel  *
   2562          1.1  kardel  * This routine saves the AGC for the current channel, switches to a new
   2563          1.1  kardel  * channel and restores the AGC for that channel. If a tunable receiver
   2564          1.1  kardel  * is not available, just fake it.
   2565          1.1  kardel  */
   2566          1.1  kardel static int
   2567          1.1  kardel wwv_qsy(
   2568          1.1  kardel 	struct peer *peer,	/* peer structure pointer */
   2569          1.1  kardel 	int	chan		/* channel */
   2570          1.1  kardel 	)
   2571          1.1  kardel {
   2572          1.1  kardel 	int rval = 0;
   2573          1.1  kardel 	struct refclockproc *pp;
   2574          1.1  kardel 	struct wwvunit *up;
   2575          1.1  kardel 
   2576          1.1  kardel 	pp = peer->procptr;
   2577  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2578          1.1  kardel 	if (up->fd_icom > 0) {
   2579          1.1  kardel 		up->mitig[up->achan].gain = up->gain;
   2580          1.1  kardel 		rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
   2581          1.1  kardel 		    qsy[chan]);
   2582          1.1  kardel 		up->achan = chan;
   2583          1.1  kardel 		up->gain = up->mitig[up->achan].gain;
   2584          1.1  kardel 	}
   2585          1.1  kardel 	return (rval);
   2586          1.1  kardel }
   2587          1.1  kardel #endif /* ICOM */
   2588          1.1  kardel 
   2589          1.1  kardel 
   2590          1.1  kardel /*
   2591          1.1  kardel  * timecode - assemble timecode string and length
   2592          1.1  kardel  *
   2593          1.1  kardel  * Prettytime format - similar to Spectracom
   2594          1.1  kardel  *
   2595          1.1  kardel  * sq yy ddd hh:mm:ss ld dut lset agc iden sig errs freq avgt
   2596          1.1  kardel  *
   2597          1.1  kardel  * s	sync indicator ('?' or ' ')
   2598          1.1  kardel  * q	error bits (hex 0-F)
   2599          1.1  kardel  * yyyy	year of century
   2600          1.1  kardel  * ddd	day of year
   2601          1.1  kardel  * hh	hour of day
   2602          1.1  kardel  * mm	minute of hour
   2603          1.1  kardel  * ss	second of minute)
   2604          1.1  kardel  * l	leap second warning (' ' or 'L')
   2605          1.1  kardel  * d	DST state ('S', 'D', 'I', or 'O')
   2606          1.1  kardel  * dut	DUT sign and magnitude (0.1 s)
   2607          1.1  kardel  * lset	minutes since last clock update
   2608          1.1  kardel  * agc	audio gain (0-255)
   2609          1.1  kardel  * iden	reference identifier (station and frequency)
   2610          1.1  kardel  * sig	signal quality (0-100)
   2611          1.1  kardel  * errs	bit errors in last minute
   2612          1.1  kardel  * freq	frequency offset (PPM)
   2613          1.1  kardel  * avgt	averaging time (s)
   2614          1.1  kardel  */
   2615          1.1  kardel static int
   2616          1.1  kardel timecode(
   2617          1.1  kardel 	struct wwvunit *up,	/* driver structure pointer */
   2618  1.1.1.1.6.1    yamt 	char *		tc,	/* target string */
   2619  1.1.1.1.6.1    yamt 	size_t		tcsiz	/* target max chars */
   2620          1.1  kardel 	)
   2621          1.1  kardel {
   2622          1.1  kardel 	struct sync *sp;
   2623          1.1  kardel 	int year, day, hour, minute, second, dut;
   2624          1.1  kardel 	char synchar, leapchar, dst;
   2625          1.1  kardel 	char cptr[50];
   2626          1.1  kardel 
   2627          1.1  kardel 
   2628          1.1  kardel 	/*
   2629          1.1  kardel 	 * Common fixed-format fields
   2630          1.1  kardel 	 */
   2631          1.1  kardel 	synchar = (up->status & INSYNC) ? ' ' : '?';
   2632          1.1  kardel 	year = up->decvec[YR].digit + up->decvec[YR + 1].digit * 10 +
   2633          1.1  kardel 	    2000;
   2634          1.1  kardel 	day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
   2635          1.1  kardel 	    up->decvec[DA + 2].digit * 100;
   2636          1.1  kardel 	hour = up->decvec[HR].digit + up->decvec[HR + 1].digit * 10;
   2637          1.1  kardel 	minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * 10;
   2638          1.1  kardel 	second = 0;
   2639          1.1  kardel 	leapchar = (up->misc & SECWAR) ? 'L' : ' ';
   2640          1.1  kardel 	dst = dstcod[(up->misc >> 4) & 0x3];
   2641          1.1  kardel 	dut = up->misc & 0x7;
   2642          1.1  kardel 	if (!(up->misc & DUTS))
   2643          1.1  kardel 		dut = -dut;
   2644  1.1.1.1.6.1    yamt 	snprintf(tc, tcsiz, "%c%1X", synchar, up->alarm);
   2645  1.1.1.1.6.1    yamt 	snprintf(cptr, sizeof(cptr),
   2646  1.1.1.1.6.1    yamt 		 " %4d %03d %02d:%02d:%02d %c%c %+d",
   2647  1.1.1.1.6.1    yamt 		 year, day, hour, minute, second, leapchar, dst, dut);
   2648  1.1.1.1.6.1    yamt 	strlcat(tc, cptr, tcsiz);
   2649          1.1  kardel 
   2650          1.1  kardel 	/*
   2651          1.1  kardel 	 * Specific variable-format fields
   2652          1.1  kardel 	 */
   2653          1.1  kardel 	sp = up->sptr;
   2654  1.1.1.1.6.1    yamt 	snprintf(cptr, sizeof(cptr), " %d %d %s %.0f %d %.1f %d",
   2655  1.1.1.1.6.1    yamt 		 up->watch, up->mitig[up->dchan].gain, sp->refid,
   2656  1.1.1.1.6.1    yamt 		 sp->metric, up->errcnt, up->freq / WWV_SEC * 1e6,
   2657  1.1.1.1.6.1    yamt 		 up->avgint);
   2658  1.1.1.1.6.1    yamt 	strlcat(tc, cptr, tcsiz);
   2659  1.1.1.1.6.1    yamt 
   2660  1.1.1.1.6.1    yamt 	return strlen(tc);
   2661          1.1  kardel }
   2662          1.1  kardel 
   2663          1.1  kardel 
   2664          1.1  kardel /*
   2665          1.1  kardel  * wwv_gain - adjust codec gain
   2666          1.1  kardel  *
   2667          1.1  kardel  * This routine is called at the end of each second. During the second
   2668          1.1  kardel  * the number of signal clips above the MAXAMP threshold (6000). If
   2669          1.1  kardel  * there are no clips, the gain is bumped up; if there are more than
   2670          1.1  kardel  * MAXCLP clips (100), it is bumped down. The decoder is relatively
   2671          1.1  kardel  * insensitive to amplitude, so this crudity works just peachy. The
   2672          1.1  kardel  * routine also jiggles the input port and selectively mutes the
   2673          1.1  kardel  * monitor.
   2674          1.1  kardel  */
   2675          1.1  kardel static void
   2676          1.1  kardel wwv_gain(
   2677          1.1  kardel 	struct peer *peer	/* peer structure pointer */
   2678          1.1  kardel 	)
   2679          1.1  kardel {
   2680          1.1  kardel 	struct refclockproc *pp;
   2681          1.1  kardel 	struct wwvunit *up;
   2682          1.1  kardel 
   2683          1.1  kardel 	pp = peer->procptr;
   2684  1.1.1.1.6.1    yamt 	up = pp->unitptr;
   2685          1.1  kardel 
   2686          1.1  kardel 	/*
   2687          1.1  kardel 	 * Apparently, the codec uses only the high order bits of the
   2688          1.1  kardel 	 * gain control field. Thus, it may take awhile for changes to
   2689          1.1  kardel 	 * wiggle the hardware bits.
   2690          1.1  kardel 	 */
   2691          1.1  kardel 	if (up->clipcnt == 0) {
   2692          1.1  kardel 		up->gain += 4;
   2693          1.1  kardel 		if (up->gain > MAXGAIN)
   2694          1.1  kardel 			up->gain = MAXGAIN;
   2695          1.1  kardel 	} else if (up->clipcnt > MAXCLP) {
   2696          1.1  kardel 		up->gain -= 4;
   2697          1.1  kardel 		if (up->gain < 0)
   2698          1.1  kardel 			up->gain = 0;
   2699          1.1  kardel 	}
   2700          1.1  kardel 	audio_gain(up->gain, up->mongain, up->port);
   2701          1.1  kardel 	up->clipcnt = 0;
   2702          1.1  kardel #if DEBUG
   2703          1.1  kardel 	if (debug > 1)
   2704          1.1  kardel 		audio_show();
   2705          1.1  kardel #endif
   2706          1.1  kardel }
   2707          1.1  kardel 
   2708          1.1  kardel 
   2709          1.1  kardel #else
   2710          1.1  kardel int refclock_wwv_bs;
   2711          1.1  kardel #endif /* REFCLOCK */
   2712