2 * refclock_wwv - clock driver for NIST WWV/H time/frequency station
8 #if defined(REFCLOCK) && defined(CLOCK_WWV)
12 #include "ntp_refclock.h"
13 #include "ntp_calendar.h"
14 #include "ntp_stdlib.h"
20 #ifdef HAVE_SYS_IOCTL_H
21 # include <sys/ioctl.h>
22 #endif /* HAVE_SYS_IOCTL_H */
31 * Audio WWV/H demodulator/decoder
33 * This driver synchronizes the computer time using data encoded in
34 * radio transmissions from NIST time/frequency stations WWV in Boulder,
35 * CO, and WWVH in Kauai, HI. Transmissions are made continuously on
36 * 2.5, 5, 10, 15 and 20 MHz in AM mode. An ordinary shortwave receiver
37 * can be tuned manually to one of these frequencies or, in the case of
38 * ICOM receivers, the receiver can be tuned automatically using this
39 * program as propagation conditions change throughout the day and
42 * The driver receives, demodulates and decodes the radio signals when
43 * connected to the audio codec of a workstation running Solaris, SunOS
44 * FreeBSD or Linux, and with a little help, other workstations with
45 * similar codecs or sound cards. In this implementation, only one audio
46 * driver and codec can be supported on a single machine.
48 * The demodulation and decoding algorithms used in this driver are
49 * based on those developed for the TAPR DSP93 development board and the
50 * TI 320C25 digital signal processor described in: Mills, D.L. A
51 * precision radio clock for WWV transmissions. Electrical Engineering
52 * Report 97-8-1, University of Delaware, August 1997, 25 pp., available
53 * from www.eecis.udel.edu/~mills/reports.htm. The algorithms described
54 * in this report have been modified somewhat to improve performance
55 * under weak signal conditions and to provide an automatic station
56 * identification feature.
58 * The ICOM code is normally compiled in the driver. It isn't used,
59 * unless the mode keyword on the server configuration command specifies
60 * a nonzero ICOM ID select code. The C-IV trace is turned on if the
61 * debug level is greater than one.
64 * Interface definitions
66 #define DEVICE_AUDIO "/dev/audio" /* audio device name */
67 #define AUDIO_BUFSIZ 320 /* audio buffer size (50 ms) */
68 #define PRECISION (-10) /* precision assumed (about 1 ms) */
69 #define DESCRIPTION "WWV/H Audio Demodulator/Decoder" /* WRU */
70 #define SECOND 8000 /* second epoch (sample rate) (Hz) */
71 #define MINUTE (SECOND * 60) /* minute epoch */
72 #define OFFSET 128 /* companded sample offset */
73 #define SIZE 256 /* decompanding table size */
74 #define MAXSIG 6000. /* max signal level reference */
75 #define MAXCLP 100 /* max clips above reference per s */
76 #define MAXSNR 30. /* max SNR reference */
77 #define DGAIN 20. /* data channel gain reference */
78 #define SGAIN 10. /* sync channel gain reference */
79 #define MAXFREQ 1. /* max frequency tolerance (125 PPM) */
80 #define PI 3.1415926535 /* the real thing */
81 #define DATSIZ (170 * MS) /* data matched filter size */
82 #define SYNSIZ (800 * MS) /* minute sync matched filter size */
83 #define MAXERR 30 /* max data bit errors in minute */
84 #define NCHAN 5 /* number of radio channels */
85 #define AUDIO_PHI 5e-6 /* dispersion growth factor */
87 #define WIGGLE 11 /* wiggle filter length */
88 #endif /* IRIG_SUCKS */
91 * General purpose status bits (status)
93 * SELV and/or SELH are set when WWV or WWVH has been heard and cleared
94 * on signal loss. SSYNC is set when the second sync pulse has been
95 * acquired and cleared by signal loss. MSYNC is set when the minute
96 * sync pulse has been acquired. DSYNC is set when a digit reaches the
97 * threshold and INSYNC is set when all nine digits have reached the
98 * threshold. The MSYNC, DSYNC and INSYNC bits are cleared only by
99 * timeout, upon which the driver starts over from scratch.
101 * DGATE is set if a data bit is invalid and BGATE is set if a BCD digit
102 * bit is invalid. SFLAG is set when during seconds 59, 0 and 1 while
103 * probing alternate frequencies. LEPDAY is set when SECWAR of the
104 * timecode is set on 30 June or 31 December. LEPSEC is set during the
105 * last minute of the day when LEPDAY is set. At the end of this minute
106 * the driver inserts second 60 in the seconds state machine and the
107 * minute sync slips a second. The SLOSS and SJITR bits are for monitor
110 #define MSYNC 0x0001 /* minute epoch sync */
111 #define SSYNC 0x0002 /* second epoch sync */
112 #define DSYNC 0x0004 /* minute units sync */
113 #define INSYNC 0x0008 /* clock synchronized */
114 #define FGATE 0x0010 /* frequency gate */
115 #define DGATE 0x0020 /* data bit error */
116 #define BGATE 0x0040 /* BCD digit bit error */
117 #define SFLAG 0x1000 /* probe flag */
118 #define LEPDAY 0x2000 /* leap second day */
119 #define LEPSEC 0x4000 /* leap second minute */
122 * Station scoreboard bits
124 * These are used to establish the signal quality for each of the five
125 * frequencies and two stations.
127 #define SYNCNG 0x0001 /* sync or SNR below threshold */
128 #define DATANG 0x0002 /* data or SNR below threshold */
129 #define ERRRNG 0x0004 /* data error */
130 #define SELV 0x0100 /* WWV station select */
131 #define SELH 0x0200 /* WWVH station select */
134 * Alarm status bits (alarm)
136 * These bits indicate various alarm conditions, which are decoded to
137 * form the quality character included in the timecode. If not tracking
138 * second sync, the SYNERR alarm is raised. The data error counter is
139 * incremented for each invalid data bit. If too many data bit errors
140 * are encountered in one minute, the MODERR alarm is raised. The DECERR
141 * alarm is raised if a maximum likelihood digit fails to compare with
142 * the current clock digit. If the probability of any miscellaneous bit
143 * or any digit falls below the threshold, the SYMERR alarm is raised.
145 #define DECERR 1 /* BCD digit compare error */
146 #define SYMERR 2 /* low bit or digit probability */
147 #define MODERR 4 /* too many data bit errors */
148 #define SYNERR 8 /* not synchronized to station */
151 * Watchcat timeouts (watch)
153 * If these timeouts expire, the status bits are mashed to zero and the
154 * driver starts from scratch. Suitably more refined procedures may be
155 * developed in future. All these are in minutes.
157 #define ACQSN 5 /* station acquisition timeout */
158 #define DIGIT 30 /* minute unit digit timeout */
159 #define HOLD 30 /* reachable timeout */
160 #define PANIC (2 * 1440) /* panic timeout */
163 * Thresholds. These establish the minimum signal level, minimum SNR and
164 * maximum jitter thresholds which establish the error and false alarm
165 * rates of the driver. The values defined here may be on the
166 * adventurous side in the interest of the highest sensitivity.
168 #define MTHR 13. /* acquisition signal gate (percent) */
169 #define TTHR 50. /* tracking signal gate (percent) */
170 #define ATHR 2000. /* acquisition amplitude threshold */
171 #define ASNR 6. /* acquisition SNR threshold (dB) */
172 #define AWND 20. /* acquisition jitter threshold (ms) */
173 #define AMIN 3 /* min bit count */
174 #define AMAX 6 /* max bit count */
175 #define QTHR 2000 /* QSY sync threshold */
176 #define QSNR 20. /* QSY sync SNR threshold (dB) */
177 #define XTHR 1000. /* QSY data threshold */
178 #define XSNR 10. /* QSY data SNR threshold (dB) */
179 #define STHR 500 /* second sync amplitude threshold */
180 #define SSNR 10. /* second sync SNR threshold */
181 #define SCMP 10 /* second sync compare threshold */
182 #define DTHR 1000 /* bit amplitude threshold */
183 #define DSNR 10. /* bit SNR threshold (dB) */
184 #define BTHR 1000 /* digit amplitude threshold */
185 #define BSNR 3. /* digit likelihood threshold (dB) */
186 #define BCMP 5 /* digit compare threshold */
189 * Tone frequency definitions. The increments are for 4.5-deg sine
192 #define MS (SECOND / 1000) /* samples per millisecond */
193 #define IN100 ((100 * 80) / SECOND) /* 100 Hz increment */
194 #define IN1000 ((1000 * 80) / SECOND) /* 1000 Hz increment */
195 #define IN1200 ((1200 * 80) / SECOND) /* 1200 Hz increment */
198 * Acquisition and tracking time constants. Usually powers of 2.
200 #define MINAVG 8 /* min time constant */
201 #define MAXAVG 1024 /* max time constant */
202 #define TCONST 16 /* data bit/digit time constant */
205 * Miscellaneous status bits (misc)
207 * These bits correspond to designated bits in the WWV/H timecode. The
208 * bit probabilities are exponentially averaged over several minutes and
209 * processed by a integrator and threshold.
211 #define DUT1 0x01 /* 56 DUT .1 */
212 #define DUT2 0x02 /* 57 DUT .2 */
213 #define DUT4 0x04 /* 58 DUT .4 */
214 #define DUTS 0x08 /* 50 DUT sign */
215 #define DST1 0x10 /* 55 DST1 leap warning */
216 #define DST2 0x20 /* 2 DST2 DST1 delayed one day */
217 #define SECWAR 0x40 /* 3 leap second warning */
220 * The on-time synchronization point for the driver is the second epoch
221 * sync pulse produced by the FIR matched filters. As the 5-ms delay of
222 * these filters is compensated, the program delay is 1.1 ms due to the
223 * 600-Hz IIR bandpass filter. The measured receiver delay is 4.7 ms and
224 * the codec delay less than 0.2 ms. The additional propagation delay
225 * specific to each receiver location can be programmed in the fudge
226 * time1 and time2 values for WWV and WWVH, respectively.
228 #define PDELAY (.0011 + .0047 + .0002) /* net system delay (s) */
231 * Table of sine values at 4.5-degree increments. This is used by the
232 * synchronous matched filter demodulators. The integral of sine-squared
233 * over one complete cycle is PI, so the table is normallized by 1 / PI.
236 0.000000e+00, 2.497431e-02, 4.979464e-02, 7.430797e-02, /* 0-3 */
237 9.836316e-02, 1.218119e-01, 1.445097e-01, 1.663165e-01, /* 4-7 */
238 1.870979e-01, 2.067257e-01, 2.250791e-01, 2.420447e-01, /* 8-11 */
239 2.575181e-01, 2.714038e-01, 2.836162e-01, 2.940800e-01, /* 12-15 */
240 3.027307e-01, 3.095150e-01, 3.143910e-01, 3.173286e-01, /* 16-19 */
241 3.183099e-01, 3.173286e-01, 3.143910e-01, 3.095150e-01, /* 20-23 */
242 3.027307e-01, 2.940800e-01, 2.836162e-01, 2.714038e-01, /* 24-27 */
243 2.575181e-01, 2.420447e-01, 2.250791e-01, 2.067257e-01, /* 28-31 */
244 1.870979e-01, 1.663165e-01, 1.445097e-01, 1.218119e-01, /* 32-35 */
245 9.836316e-02, 7.430797e-02, 4.979464e-02, 2.497431e-02, /* 36-39 */
246 -0.000000e+00, -2.497431e-02, -4.979464e-02, -7.430797e-02, /* 40-43 */
247 -9.836316e-02, -1.218119e-01, -1.445097e-01, -1.663165e-01, /* 44-47 */
248 -1.870979e-01, -2.067257e-01, -2.250791e-01, -2.420447e-01, /* 48-51 */
249 -2.575181e-01, -2.714038e-01, -2.836162e-01, -2.940800e-01, /* 52-55 */
250 -3.027307e-01, -3.095150e-01, -3.143910e-01, -3.173286e-01, /* 56-59 */
251 -3.183099e-01, -3.173286e-01, -3.143910e-01, -3.095150e-01, /* 60-63 */
252 -3.027307e-01, -2.940800e-01, -2.836162e-01, -2.714038e-01, /* 64-67 */
253 -2.575181e-01, -2.420447e-01, -2.250791e-01, -2.067257e-01, /* 68-71 */
254 -1.870979e-01, -1.663165e-01, -1.445097e-01, -1.218119e-01, /* 72-75 */
255 -9.836316e-02, -7.430797e-02, -4.979464e-02, -2.497431e-02, /* 76-79 */
256 0.000000e+00}; /* 80 */
259 * Decoder operations at the end of each second are driven by a state
260 * machine. The transition matrix consists of a dispatch table indexed
261 * by second number. Each entry in the table contains a case switch
262 * number and argument.
265 int sw; /* case switch number */
266 int arg; /* argument */
270 * Case switch numbers
272 #define IDLE 0 /* no operation */
273 #define COEF 1 /* BCD bit */
274 #define COEF2 2 /* BCD bit ignored */
275 #define DECIM9 3 /* BCD digit 0-9 */
276 #define DECIM6 4 /* BCD digit 0-6 */
277 #define DECIM3 5 /* BCD digit 0-3 */
278 #define DECIM2 6 /* BCD digit 0-2 */
279 #define MSCBIT 7 /* miscellaneous bit */
280 #define MSC20 8 /* miscellaneous bit */
281 #define MSC21 9 /* QSY probe channel */
282 #define MIN1 10 /* minute */
283 #define MIN2 11 /* leap second */
284 #define SYNC2 12 /* QSY data channel */
285 #define SYNC3 13 /* QSY data channel */
288 * Offsets in decoding matrix
290 #define MN 0 /* minute digits (2) */
291 #define HR 2 /* hour digits (2) */
292 #define DA 4 /* day digits (3) */
293 #define YR 7 /* year digits (2) */
295 struct progx progx[] = {
296 {SYNC2, 0}, /* 0 latch sync max */
297 {SYNC3, 0}, /* 1 QSY data channel */
298 {MSCBIT, DST2}, /* 2 dst2 */
299 {MSCBIT, SECWAR}, /* 3 lw */
300 {COEF, 0}, /* 4 1 year units */
304 {DECIM9, YR}, /* 8 */
305 {IDLE, 0}, /* 9 p1 */
306 {COEF, 0}, /* 10 1 minute units */
307 {COEF, 1}, /* 11 2 */
308 {COEF, 2}, /* 12 4 */
309 {COEF, 3}, /* 13 8 */
310 {DECIM9, MN}, /* 14 */
311 {COEF, 0}, /* 15 10 minute tens */
312 {COEF, 1}, /* 16 20 */
313 {COEF, 2}, /* 17 40 */
314 {COEF2, 3}, /* 18 80 (not used) */
315 {DECIM6, MN + 1}, /* 19 p2 */
316 {COEF, 0}, /* 20 1 hour units */
317 {COEF, 1}, /* 21 2 */
318 {COEF, 2}, /* 22 4 */
319 {COEF, 3}, /* 23 8 */
320 {DECIM9, HR}, /* 24 */
321 {COEF, 0}, /* 25 10 hour tens */
322 {COEF, 1}, /* 26 20 */
323 {COEF2, 2}, /* 27 40 (not used) */
324 {COEF2, 3}, /* 28 80 (not used) */
325 {DECIM2, HR + 1}, /* 29 p3 */
326 {COEF, 0}, /* 30 1 day units */
327 {COEF, 1}, /* 31 2 */
328 {COEF, 2}, /* 32 4 */
329 {COEF, 3}, /* 33 8 */
330 {DECIM9, DA}, /* 34 */
331 {COEF, 0}, /* 35 10 day tens */
332 {COEF, 1}, /* 36 20 */
333 {COEF, 2}, /* 37 40 */
334 {COEF, 3}, /* 38 80 */
335 {DECIM9, DA + 1}, /* 39 p4 */
336 {COEF, 0}, /* 40 100 day hundreds */
337 {COEF, 1}, /* 41 200 */
338 {COEF2, 2}, /* 42 400 (not used) */
339 {COEF2, 3}, /* 43 800 (not used) */
340 {DECIM3, DA + 2}, /* 44 */
345 {IDLE, 0}, /* 49 p5 */
346 {MSCBIT, DUTS}, /* 50 dut+- */
347 {COEF, 0}, /* 51 10 year tens */
348 {COEF, 1}, /* 52 20 */
349 {COEF, 2}, /* 53 40 */
350 {COEF, 3}, /* 54 80 */
351 {MSC20, DST1}, /* 55 dst1 */
352 {MSCBIT, DUT1}, /* 56 0.1 dut */
353 {MSCBIT, DUT2}, /* 57 0.2 */
354 {MSC21, DUT4}, /* 58 0.4 QSY probe channel */
355 {MIN1, 0}, /* 59 p6 latch sync min */
356 {MIN2, 0} /* 60 leap second */
360 * BCD coefficients for maximum likelihood digit decode
362 #define P15 1. /* max positive number */
363 #define N15 -1. /* max negative number */
368 #define P9 (P15 / 4) /* mark (+1) */
369 #define N9 (N15 / 4) /* space (-1) */
372 {N9, N9, N9, N9}, /* 0 */
373 {P9, N9, N9, N9}, /* 1 */
374 {N9, P9, N9, N9}, /* 2 */
375 {P9, P9, N9, N9}, /* 3 */
376 {N9, N9, P9, N9}, /* 4 */
377 {P9, N9, P9, N9}, /* 5 */
378 {N9, P9, P9, N9}, /* 6 */
379 {P9, P9, P9, N9}, /* 7 */
380 {N9, N9, N9, P9}, /* 8 */
381 {P9, N9, N9, P9}, /* 9 */
382 {0, 0, 0, 0} /* backstop */
386 * Digits 0-6 (minute tens)
388 #define P6 (P15 / 3) /* mark (+1) */
389 #define N6 (N15 / 3) /* space (-1) */
392 {N6, N6, N6, 0}, /* 0 */
393 {P6, N6, N6, 0}, /* 1 */
394 {N6, P6, N6, 0}, /* 2 */
395 {P6, P6, N6, 0}, /* 3 */
396 {N6, N6, P6, 0}, /* 4 */
397 {P6, N6, P6, 0}, /* 5 */
398 {N6, P6, P6, 0}, /* 6 */
399 {0, 0, 0, 0} /* backstop */
403 * Digits 0-3 (day hundreds)
405 #define P3 (P15 / 2) /* mark (+1) */
406 #define N3 (N15 / 2) /* space (-1) */
409 {N3, N3, 0, 0}, /* 0 */
410 {P3, N3, 0, 0}, /* 1 */
411 {N3, P3, 0, 0}, /* 2 */
412 {P3, P3, 0, 0}, /* 3 */
413 {0, 0, 0, 0} /* backstop */
417 * Digits 0-2 (hour tens)
419 #define P2 (P15 / 2) /* mark (+1) */
420 #define N2 (N15 / 2) /* space (-1) */
423 {N2, N2, 0, 0}, /* 0 */
424 {P2, N2, 0, 0}, /* 1 */
425 {N2, P2, 0, 0}, /* 2 */
426 {0, 0, 0, 0} /* backstop */
430 * DST decode (DST2 DST1) for prettyprint
433 'S', /* 00 standard time */
434 'I', /* 01 set clock ahead at 0200 local */
435 'O', /* 10 set clock back at 0200 local */
436 'D' /* 11 daylight time */
440 * The decoding matrix consists of nine row vectors, one for each digit
441 * of the timecode. The digits are stored from least to most significant
442 * order. The maximum likelihood timecode is formed from the digits
443 * corresponding to the maximum likelihood values reading in the
444 * opposite order: yy ddd hh:mm.
447 int radix; /* radix (3, 4, 6, 10) */
448 int digit; /* current clock digit */
449 int mldigit; /* maximum likelihood digit */
450 int phase; /* maximum likelihood digit phase */
451 int count; /* match count */
452 double digprb; /* max digit probability */
453 double digsnr; /* likelihood function (dB) */
454 double like[10]; /* likelihood integrator 0-9 */
458 * The station structure is used to acquire the minute pulse from WWV
459 * and/or WWVH. These stations are distinguished by the frequency used
460 * for the second and minute sync pulses, 1000 Hz for WWV and 1200 Hz
461 * for WWVH. Other than frequency, the format is the same.
464 double epoch; /* accumulated epoch differences */
465 double maxamp; /* sync max envelope (square) */
466 double noiamp; /* sync noise envelope (square) */
467 long pos; /* max amplitude position */
468 long lastpos; /* last max position */
469 long mepoch; /* minute synch epoch */
471 double amp; /* sync amplitude (I, Q squares) */
472 double synamp; /* sync max envelope at 800 ms */
473 double synmax; /* sync envelope at 0 s */
474 double synmin; /* sync envelope at 59, 1 s */
475 double synsnr; /* sync signal SNR */
476 int count; /* bit counter */
477 char refid[5]; /* reference identifier */
478 int select; /* select bits */
479 int reach; /* reachability register */
483 * The channel structure is used to mitigate between channels.
486 int gain; /* audio gain */
487 double sigamp; /* data max envelope (square) */
488 double noiamp; /* data noise envelope (square) */
489 double datsnr; /* data signal SNR */
490 struct sync wwv; /* wwv station */
491 struct sync wwvh; /* wwvh station */
495 * WWV unit control structure
498 l_fp timestamp; /* audio sample timestamp */
499 l_fp tick; /* audio sample increment */
500 double phase, freq; /* logical clock phase and frequency */
501 double monitor; /* audio monitor point */
502 int fd_icom; /* ICOM file descriptor */
503 int errflg; /* error flags */
504 int watch; /* watchcat */
507 * Audio codec variables
509 double comp[SIZE]; /* decompanding table */
510 int port; /* codec port */
511 int gain; /* codec gain */
512 int mongain; /* codec monitor gain */
513 int clipcnt; /* sample clipped count */
515 l_fp wigwag; /* wiggle accumulator */
516 int wp; /* wiggle filter pointer */
517 l_fp wiggle[WIGGLE]; /* wiggle filter */
518 l_fp wigbot[WIGGLE]; /* wiggle bottom fisher*/
519 #endif /* IRIG_SUCKS */
522 * Variables used to establish basic system timing
524 int avgint; /* master time constant */
525 int tepoch; /* sync epoch median */
526 int yepoch; /* sync epoch */
527 int repoch; /* buffered sync epoch */
528 double epomax; /* second sync amplitude */
529 double eposnr; /* second sync SNR */
530 double irig; /* data I channel amplitude */
531 double qrig; /* data Q channel amplitude */
532 int datapt; /* 100 Hz ramp */
533 double datpha; /* 100 Hz VFO control */
534 int rphase; /* second sample counter */
535 long mphase; /* minute sample counter */
538 * Variables used to mitigate which channel to use
540 struct chan mitig[NCHAN]; /* channel data */
541 struct sync *sptr; /* station pointer */
542 int dchan; /* data channel */
543 int schan; /* probe channel */
544 int achan; /* active channel */
547 * Variables used by the clock state machine
549 struct decvec decvec[9]; /* decoding matrix */
550 int rsec; /* seconds counter */
551 int digcnt; /* count of digits synchronized */
554 * Variables used to estimate signal levels and bit/digit
557 double sigsig; /* data max signal */
558 double sigamp; /* data max envelope (square) */
559 double noiamp; /* data noise envelope (square) */
560 double datsnr; /* data SNR (dB) */
563 * Variables used to establish status and alarm conditions
565 int status; /* status bits */
566 int alarm; /* alarm flashers */
567 int misc; /* miscellaneous timecode bits */
568 int errcnt; /* data bit error counter */
569 int errbit; /* data bit errors in minute */
573 * Function prototypes
575 static int wwv_start P((int, struct peer *));
576 static void wwv_shutdown P((int, struct peer *));
577 static void wwv_receive P((struct recvbuf *));
578 static void wwv_poll P((int, struct peer *));
581 * More function prototypes
583 static void wwv_epoch P((struct peer *));
584 static void wwv_rf P((struct peer *, double));
585 static void wwv_endpoc P((struct peer *, int));
586 static void wwv_rsec P((struct peer *, double));
587 static void wwv_qrz P((struct peer *, struct sync *,
589 static void wwv_corr4 P((struct peer *, struct decvec *,
590 double [], double [][4]));
591 static void wwv_gain P((struct peer *));
592 static void wwv_tsec P((struct wwvunit *));
593 static double wwv_data P((struct wwvunit *, double));
594 static int timecode P((struct wwvunit *, char *));
595 static double wwv_snr P((double, double));
596 static int carry P((struct decvec *));
597 static void wwv_newchan P((struct peer *));
598 static void wwv_newgame P((struct peer *));
599 static double wwv_metric P((struct sync *));
601 static int wwv_qsy P((struct peer *, int));
604 static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) */
609 struct refclock refclock_wwv = {
610 wwv_start, /* start up driver */
611 wwv_shutdown, /* shut down driver */
612 wwv_poll, /* transmit poll message */
613 noentry, /* not used (old wwv_control) */
614 noentry, /* initialize driver (not used) */
615 noentry, /* not used (old wwv_buginfo) */
616 NOFLAGS /* not used */
621 * wwv_start - open the devices and initialize data for processing
625 int unit, /* instance number (used by PCM) */
626 struct peer *peer /* peer structure pointer */
629 struct refclockproc *pp;
638 int fd; /* file descriptor */
640 double step; /* codec adjustment */
645 fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
654 * Allocate and initialize unit structure
656 if (!(up = (struct wwvunit *)emalloc(sizeof(struct wwvunit)))) {
660 memset(up, 0, sizeof(struct wwvunit));
662 pp->unitptr = (caddr_t)up;
663 pp->io.clock_recv = wwv_receive;
664 pp->io.srcclock = (caddr_t)peer;
667 if (!io_addclock(&pp->io)) {
674 * Initialize miscellaneous variables
676 peer->precision = PRECISION;
677 pp->clockdesc = DESCRIPTION;
680 * The companded samples are encoded sign-magnitude. The table
681 * contains all the 256 values in the interest of speed.
683 up->comp[0] = up->comp[OFFSET] = 0.;
684 up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
685 up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
687 for (i = 3; i < OFFSET; i++) {
688 up->comp[i] = up->comp[i - 1] + step;
689 up->comp[OFFSET + i] = -up->comp[i];
693 DTOLFP(1. / SECOND, &up->tick);
696 * Initialize the decoding matrix with the radix for each digit
699 up->decvec[MN].radix = 10; /* minutes */
700 up->decvec[MN + 1].radix = 6;
701 up->decvec[HR].radix = 10; /* hours */
702 up->decvec[HR + 1].radix = 3;
703 up->decvec[DA].radix = 10; /* days */
704 up->decvec[DA + 1].radix = 10;
705 up->decvec[DA + 2].radix = 4;
706 up->decvec[YR].radix = 10; /* years */
707 up->decvec[YR + 1].radix = 10;
709 up->schan = up->achan = 3;
712 * Initialize autotune if available. Start out at 15 MHz. Note
713 * that the ICOM select code must be less than 128, so the high
714 * order bit can be used to select the line speed.
722 if (peer->ttl != 0) {
723 if (peer->ttl & 0x80)
724 up->fd_icom = icom_init("/dev/icom", B1200,
727 up->fd_icom = icom_init("/dev/icom", B9600,
730 if (up->fd_icom > 0) {
731 if ((temp = wwv_qsy(peer, up->schan)) != 0) {
732 NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
734 "icom: radio not found");
735 up->errflg = CEVNT_FAULT;
739 NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
741 "icom: autotune enabled");
750 * wwv_shutdown - shut down the clock
754 int unit, /* instance number (not used) */
755 struct peer *peer /* peer structure pointer */
758 struct refclockproc *pp;
762 up = (struct wwvunit *)pp->unitptr;
763 io_closeclock(&pp->io);
771 * wwv_receive - receive data from the audio device
773 * This routine reads input samples and adjusts the logical clock to
774 * track the A/D sample clock by dropping or duplicating codec samples.
775 * It also controls the A/D signal level with an AGC loop to mimimize
776 * quantization noise and avoid overload.
780 struct recvbuf *rbufp /* receive buffer structure pointer */
784 struct refclockproc *pp;
790 double sample; /* codec sample */
791 u_char *dpt; /* buffer pointer */
792 int bufcnt; /* buffer counter */
795 peer = (struct peer *)rbufp->recv_srcclock;
797 up = (struct wwvunit *)pp->unitptr;
800 * Main loop - read until there ain't no more. Note codec
801 * samples are bit-inverted.
803 DTOLFP((double)rbufp->recv_length / SECOND, <emp);
804 L_SUB(&rbufp->recv_time, <emp);
805 up->timestamp = rbufp->recv_time;
806 dpt = rbufp->recv_buffer;
807 for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
808 sample = up->comp[~*dpt++ & 0xff];
811 * Clip noise spikes greater than MAXSIG. If no clips,
812 * increase the gain a tad; if the clips are too high,
815 if (sample > MAXSIG) {
818 } else if (sample < -MAXSIG) {
824 * Variable frequency oscillator. The codec oscillator
825 * runs at the nominal rate of 8000 samples per second,
826 * or 125 us per sample. A frequency change of one unit
827 * results in either duplicating or deleting one sample
828 * per second, which results in a frequency change of
831 up->phase += up->freq / SECOND;
832 if (up->phase >= .5) {
834 } else if (up->phase < -.5) {
836 wwv_rf(peer, sample);
837 wwv_rf(peer, sample);
839 wwv_rf(peer, sample);
841 L_ADD(&up->timestamp, &up->tick);
845 * Set the input port and monitor gain for the next buffer.
847 if (pp->sloppyclockflag & CLK_FLAG2)
851 if (pp->sloppyclockflag & CLK_FLAG3)
852 up->mongain = MONGAIN;
859 * wwv_poll - called by the transmit procedure
861 * This routine keeps track of status. If no offset samples have been
862 * processed during a poll interval, a timeout event is declared. If
863 * errors have have occurred during the interval, they are reported as
864 * well. Once the clock is set, it always appears reachable, unless
865 * reset by watchdog timeout.
869 int unit, /* instance number (not used) */
870 struct peer *peer /* peer structure pointer */
873 struct refclockproc *pp;
877 up = (struct wwvunit *)pp->unitptr;
878 if (pp->coderecv == pp->codeproc)
879 up->errflg = CEVNT_TIMEOUT;
881 refclock_report(peer, up->errflg);
888 * wwv_rf - process signals and demodulate to baseband
890 * This routine grooms and filters decompanded raw audio samples. The
891 * output signals include the 100-Hz baseband data signal in quadrature
892 * form, plus the epoch index of the second sync signal and the second
893 * index of the minute sync signal.
895 * There are two 1-s ramps used by this program. Both count the 8000
896 * logical clock samples spanning exactly one second. The epoch ramp
897 * counts the samples starting at an arbitrary time. The rphase ramp
898 * counts the samples starting at the 5-ms second sync pulse found
899 * during the epoch ramp.
901 * There are two 1-m ramps used by this program. The mphase ramp counts
902 * the 480,000 logical clock samples spanning exactly one minute and
903 * starting at an arbitrary time. The rsec ramp counts the 60 seconds of
904 * the minute starting at the 800-ms minute sync pulse found during the
905 * mphase ramp. The rsec ramp drives the seconds state machine to
906 * determine the bits and digits of the timecode.
908 * Demodulation operations are based on three synthesized quadrature
909 * sinusoids: 100 Hz for the data signal, 1000 Hz for the WWV sync
910 * signal and 1200 Hz for the WWVH sync signal. These drive synchronous
911 * matched filters for the data signal (170 ms at 100 Hz), WWV minute
912 * sync signal (800 ms at 1000 Hz) and WWVH minute sync signal (800 ms
913 * at 1200 Hz). Two additional matched filters are switched in
914 * as required for the WWV second sync signal (5 ms at 1000 Hz) and
915 * WWVH second sync signal (5 ms at 1200 Hz).
919 struct peer *peer, /* peerstructure pointer */
920 double isig /* input signal */
923 struct refclockproc *pp;
927 static double lpf[5]; /* 150-Hz lpf delay line */
928 double data; /* lpf output */
929 static double bpf[9]; /* 1000/1200-Hz bpf delay line */
930 double syncx; /* bpf output */
931 static double mf[41]; /* 1000/1200-Hz mf delay line */
932 double mfsync; /* mf output */
934 static int iptr; /* data channel pointer */
935 static double ibuf[DATSIZ]; /* data I channel delay line */
936 static double qbuf[DATSIZ]; /* data Q channel delay line */
938 static int jptr; /* sync channel pointer */
939 static double cibuf[SYNSIZ]; /* wwv I channel delay line */
940 static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */
941 static double ciamp; /* wwv I channel amplitude */
942 static double cqamp; /* wwv Q channel amplitude */
943 static int csinptr; /* wwv channel phase */
944 static double hibuf[SYNSIZ]; /* wwvh I channel delay line */
945 static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */
946 static double hiamp; /* wwvh I channel amplitude */
947 static double hqamp; /* wwvh Q channel amplitude */
948 static int hsinptr; /* wwvh channels phase */
950 static double epobuf[SECOND]; /* epoch sync comb filter */
951 static double epomax; /* epoch sync amplitude buffer */
952 static int epopos; /* epoch sync position buffer */
954 static int iniflg; /* initialization flag */
955 int epoch; /* comb filter index */
956 int pdelay; /* propagation delay (samples) */
961 up = (struct wwvunit *)pp->unitptr;
965 memset((char *)lpf, 0, sizeof(lpf));
966 memset((char *)bpf, 0, sizeof(bpf));
967 memset((char *)mf, 0, sizeof(mf));
968 memset((char *)ibuf, 0, sizeof(ibuf));
969 memset((char *)qbuf, 0, sizeof(qbuf));
970 memset((char *)cibuf, 0, sizeof(cibuf));
971 memset((char *)cqbuf, 0, sizeof(cqbuf));
972 memset((char *)hibuf, 0, sizeof(hibuf));
973 memset((char *)hqbuf, 0, sizeof(hqbuf));
974 memset((char *)epobuf, 0, sizeof(epobuf));
978 * Baseband data demodulation. The 100-Hz subcarrier is
979 * extracted using a 150-Hz IIR lowpass filter. This attenuates
980 * the 1000/1200-Hz sync signals, as well as the 440-Hz and
981 * 600-Hz tones and most of the noise and voice modulation
984 * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
985 * passband ripple, -50 dB stopband ripple.
987 data = (lpf[4] = lpf[3]) * 8.360961e-01;
988 data += (lpf[3] = lpf[2]) * -3.481740e+00;
989 data += (lpf[2] = lpf[1]) * 5.452988e+00;
990 data += (lpf[1] = lpf[0]) * -3.807229e+00;
991 lpf[0] = isig - data;
992 data = lpf[0] * 3.281435e-03
993 + lpf[1] * -1.149947e-02
994 + lpf[2] * 1.654858e-02
995 + lpf[3] * -1.149947e-02
996 + lpf[4] * 3.281435e-03;
999 * The I and Q quadrature data signals are produced by
1000 * multiplying the filtered signal by 100-Hz sine and cosine
1001 * signals, respectively. The data signals are demodulated by
1002 * 170-ms synchronous matched filters to produce the amplitude
1003 * and phase signals used by the decoder.
1006 up->datapt = (up->datapt + IN100) % 80;
1007 dtemp = sintab[i] * data / DATSIZ * DGAIN;
1008 up->irig -= ibuf[iptr];
1012 dtemp = sintab[i] * data / DATSIZ * DGAIN;
1013 up->qrig -= qbuf[iptr];
1016 iptr = (iptr + 1) % DATSIZ;
1019 * Baseband sync demodulation. The 1000/1200 sync signals are
1020 * extracted using a 600-Hz IIR bandpass filter. This removes
1021 * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz
1022 * tones and most of the noise and voice modulation components.
1024 * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
1025 * passband ripple, -50 dB stopband ripple.
1027 syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
1028 syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
1029 syncx += (bpf[6] = bpf[5]) * 8.110921e+00;
1030 syncx += (bpf[5] = bpf[4]) * -1.517732e+01;
1031 syncx += (bpf[4] = bpf[3]) * 1.975197e+01;
1032 syncx += (bpf[3] = bpf[2]) * -1.814365e+01;
1033 syncx += (bpf[2] = bpf[1]) * 1.159783e+01;
1034 syncx += (bpf[1] = bpf[0]) * -4.735040e+00;
1035 bpf[0] = isig - syncx;
1036 syncx = bpf[0] * 8.203628e-03
1037 + bpf[1] * -2.375732e-02
1038 + bpf[2] * 3.353214e-02
1039 + bpf[3] * -4.080258e-02
1040 + bpf[4] * 4.605479e-02
1041 + bpf[5] * -4.080258e-02
1042 + bpf[6] * 3.353214e-02
1043 + bpf[7] * -2.375732e-02
1044 + bpf[8] * 8.203628e-03;
1047 * The I and Q quadrature minute sync signals are produced by
1048 * multiplying the filtered signal by 1000-Hz (WWV) and 1200-Hz
1049 * (WWVH) sine and cosine signals, respectively. The resulting
1050 * signals are demodulated by 800-ms synchronous matched filters
1051 * to synchronize the second and minute and to detect which one
1052 * (or both) the WWV or WWVH signal is present.
1054 * Note the master timing ramps, which run continuously. The
1055 * minute counter (mphase) counts the samples in the minute,
1056 * while the second counter (epoch) counts the samples in the
1059 up->mphase = (up->mphase + 1) % MINUTE;
1060 epoch = up->mphase % SECOND;
1062 csinptr = (csinptr + IN1000) % 80;
1063 dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
1064 ciamp = ciamp - cibuf[jptr] + dtemp;
1065 cibuf[jptr] = dtemp;
1067 dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
1068 cqamp = cqamp - cqbuf[jptr] + dtemp;
1069 cqbuf[jptr] = dtemp;
1070 sp = &up->mitig[up->schan].wwv;
1071 dtemp = ciamp * ciamp + cqamp * cqamp;
1073 if (!(up->status & MSYNC))
1074 wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime1 *
1077 hsinptr = (hsinptr + IN1200) % 80;
1078 dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
1079 hiamp = hiamp - hibuf[jptr] + dtemp;
1080 hibuf[jptr] = dtemp;
1082 dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
1083 hqamp = hqamp - hqbuf[jptr] + dtemp;
1084 hqbuf[jptr] = dtemp;
1085 sp = &up->mitig[up->schan].wwvh;
1086 dtemp = hiamp * hiamp + hqamp * hqamp;
1088 if (!(up->status & MSYNC))
1089 wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime2 *
1091 jptr = (jptr + 1) % SYNSIZ;
1094 * The following section is called once per minute. It does
1095 * housekeeping and timeout functions and empties the dustbins.
1097 if (up->mphase == 0) {
1099 if (!(up->status & MSYNC)) {
1102 * If minute sync has not been acquired before
1103 * timeout, or if no signal is heard, the
1104 * program cycles to the next frequency and
1108 if (!(up->status & (SELV | SELH)) || up->watch >
1112 if (up->fd_icom > 0) {
1113 up->schan = (up->schan + 1) %
1115 wwv_qsy(peer, up->schan);
1122 * If the leap bit is set, set the minute epoch
1123 * back one second so the station processes
1124 * don't miss a beat.
1126 if (up->status & LEPSEC) {
1127 up->mphase -= SECOND;
1129 up->mphase += MINUTE;
1135 * When the channel metric reaches threshold and the second
1136 * counter matches the minute epoch within the second, the
1137 * driver has synchronized to the station. The second number is
1138 * the remaining seconds until the next minute epoch, while the
1139 * sync epoch is zero. Watch out for the first second; if
1140 * already synchronized to the second, the buffered sync epoch
1143 if (up->status & MSYNC) {
1145 } else if ((sp = up->sptr) != NULL) {
1148 if (sp->count >= AMIN && epoch == sp->mepoch % SECOND) {
1149 up->rsec = 60 - sp->mepoch / SECOND;
1151 up->status |= MSYNC;
1153 if (!(up->status & SSYNC))
1154 up->repoch = up->yepoch = epoch;
1156 up->repoch = up->yepoch;
1157 for (i = 0; i < NCHAN; i++) {
1159 cp->wwv.count = cp->wwv.reach = 0;
1160 cp->wwvh.count = cp->wwvh.reach = 0;
1166 * The second sync pulse is extracted using 5-ms (40 sample) FIR
1167 * matched filters at 1000 Hz for WWV or 1200 Hz for WWVH. This
1168 * pulse is used for the most precise synchronization, since if
1169 * provides a resolution of one sample (125 us). The filters run
1170 * only if the station has been reliably determined.
1172 if (up->status & SELV) {
1173 pdelay = (int)(pp->fudgetime1 * SECOND);
1176 * WWV FIR matched filter, five cycles of 1000-Hz
1180 mfsync = (mf[39] = mf[38]) * 4.224514e-02;
1181 mfsync += (mf[38] = mf[37]) * 5.974365e-02;
1182 mfsync += (mf[37] = mf[36]) * 4.224514e-02;
1184 mfsync += (mf[35] = mf[34]) * -4.224514e-02;
1185 mfsync += (mf[34] = mf[33]) * -5.974365e-02;
1186 mfsync += (mf[33] = mf[32]) * -4.224514e-02;
1188 mfsync += (mf[31] = mf[30]) * 4.224514e-02;
1189 mfsync += (mf[30] = mf[29]) * 5.974365e-02;
1190 mfsync += (mf[29] = mf[28]) * 4.224514e-02;
1192 mfsync += (mf[27] = mf[26]) * -4.224514e-02;
1193 mfsync += (mf[26] = mf[25]) * -5.974365e-02;
1194 mfsync += (mf[25] = mf[24]) * -4.224514e-02;
1196 mfsync += (mf[23] = mf[22]) * 4.224514e-02;
1197 mfsync += (mf[22] = mf[21]) * 5.974365e-02;
1198 mfsync += (mf[21] = mf[20]) * 4.224514e-02;
1200 mfsync += (mf[19] = mf[18]) * -4.224514e-02;
1201 mfsync += (mf[18] = mf[17]) * -5.974365e-02;
1202 mfsync += (mf[17] = mf[16]) * -4.224514e-02;
1204 mfsync += (mf[15] = mf[14]) * 4.224514e-02;
1205 mfsync += (mf[14] = mf[13]) * 5.974365e-02;
1206 mfsync += (mf[13] = mf[12]) * 4.224514e-02;
1208 mfsync += (mf[11] = mf[10]) * -4.224514e-02;
1209 mfsync += (mf[10] = mf[9]) * -5.974365e-02;
1210 mfsync += (mf[9] = mf[8]) * -4.224514e-02;
1212 mfsync += (mf[7] = mf[6]) * 4.224514e-02;
1213 mfsync += (mf[6] = mf[5]) * 5.974365e-02;
1214 mfsync += (mf[5] = mf[4]) * 4.224514e-02;
1216 mfsync += (mf[3] = mf[2]) * -4.224514e-02;
1217 mfsync += (mf[2] = mf[1]) * -5.974365e-02;
1218 mfsync += (mf[1] = mf[0]) * -4.224514e-02;
1220 } else if (up->status & SELH) {
1221 pdelay = (int)(pp->fudgetime2 * SECOND);
1224 * WWVH FIR matched filter, six cycles of 1200-Hz
1228 mfsync = (mf[39] = mf[38]) * 4.833363e-02;
1229 mfsync += (mf[38] = mf[37]) * 5.681959e-02;
1230 mfsync += (mf[37] = mf[36]) * 1.846180e-02;
1231 mfsync += (mf[36] = mf[35]) * -3.511644e-02;
1232 mfsync += (mf[35] = mf[34]) * -5.974365e-02;
1233 mfsync += (mf[34] = mf[33]) * -3.511644e-02;
1234 mfsync += (mf[33] = mf[32]) * 1.846180e-02;
1235 mfsync += (mf[32] = mf[31]) * 5.681959e-02;
1236 mfsync += (mf[31] = mf[30]) * 4.833363e-02;
1238 mfsync += (mf[29] = mf[28]) * -4.833363e-02;
1239 mfsync += (mf[28] = mf[27]) * -5.681959e-02;
1240 mfsync += (mf[27] = mf[26]) * -1.846180e-02;
1241 mfsync += (mf[26] = mf[25]) * 3.511644e-02;
1242 mfsync += (mf[25] = mf[24]) * 5.974365e-02;
1243 mfsync += (mf[24] = mf[23]) * 3.511644e-02;
1244 mfsync += (mf[23] = mf[22]) * -1.846180e-02;
1245 mfsync += (mf[22] = mf[21]) * -5.681959e-02;
1246 mfsync += (mf[21] = mf[20]) * -4.833363e-02;
1248 mfsync += (mf[19] = mf[18]) * 4.833363e-02;
1249 mfsync += (mf[18] = mf[17]) * 5.681959e-02;
1250 mfsync += (mf[17] = mf[16]) * 1.846180e-02;
1251 mfsync += (mf[16] = mf[15]) * -3.511644e-02;
1252 mfsync += (mf[15] = mf[14]) * -5.974365e-02;
1253 mfsync += (mf[14] = mf[13]) * -3.511644e-02;
1254 mfsync += (mf[13] = mf[12]) * 1.846180e-02;
1255 mfsync += (mf[12] = mf[11]) * 5.681959e-02;
1256 mfsync += (mf[11] = mf[10]) * 4.833363e-02;
1258 mfsync += (mf[9] = mf[8]) * -4.833363e-02;
1259 mfsync += (mf[8] = mf[7]) * -5.681959e-02;
1260 mfsync += (mf[7] = mf[6]) * -1.846180e-02;
1261 mfsync += (mf[6] = mf[5]) * 3.511644e-02;
1262 mfsync += (mf[5] = mf[4]) * 5.974365e-02;
1263 mfsync += (mf[4] = mf[3]) * 3.511644e-02;
1264 mfsync += (mf[3] = mf[2]) * -1.846180e-02;
1265 mfsync += (mf[2] = mf[1]) * -5.681959e-02;
1266 mfsync += (mf[1] = mf[0]) * -4.833363e-02;
1274 * Enhance the seconds sync pulse using a 1-s (8000-sample) comb
1275 * filter. Correct for the FIR matched filter delay, which is 5
1276 * ms for both the WWV and WWVH filters, and also for the
1277 * propagation delay. Once each second look for second sync. If
1278 * not in minute sync, fiddle the codec gain. Note the SNR is
1279 * computed from the maximum sample and the two samples 6 ms
1280 * before and 6 ms after it, so if we slip more than a cycle the
1281 * SNR should plummet.
1283 dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
1285 if (dtemp > epomax) {
1292 up->epomax = epomax;
1293 k = epopos - 6 * MS;
1296 j = epopos + 6 * MS;
1299 up->eposnr = wwv_snr(epomax, max(abs(epobuf[k]),
1301 epopos -= pdelay + 5 * MS;
1304 wwv_endpoc(peer, epopos);
1305 if (!(up->status & SSYNC))
1306 up->alarm |= SYNERR;
1308 if (!(up->status & MSYNC))
1315 * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse
1317 * This routine implements a virtual station process used to acquire
1318 * minute sync and to mitigate among the ten frequency and station
1319 * combinations. During minute sync acquisition the process probes each
1320 * frequency in turn for the minute pulse from either station, which
1321 * involves searching through the entire minute of samples. After
1322 * finding a candidate, the process searches only the seconds before and
1323 * after the candidate for the signal and all other seconds for the
1326 * Students of radar receiver technology will discover this algorithm
1327 * amounts to a range gate discriminator. The discriminator requires
1328 * that the peak minute pulse amplitude be at least 2000 and the SNR be
1329 * at least 6 dB. In addition after finding a candidate, The peak second
1330 * pulse amplitude must be at least 2000, the SNR at least 6 dB and the
1331 * difference between the current and previous epoch must be less than
1332 * 7.5 ms, which corresponds to a frequency error of 125 PPM.. A compare
1333 * counter keeps track of the number of successive intervals which
1334 * satisfy these criteria.
1336 * Note that, while the minute pulse is found by by the discriminator,
1337 * the actual value is determined from the second epoch. The assumption
1338 * is that the discriminator peak occurs about 800 ms into the second,
1339 * so the timing is retarted to the previous second epoch.
1343 struct peer *peer, /* peer structure pointer */
1344 struct sync *sp, /* sync channel structure */
1345 double syncx, /* bandpass filtered sync signal */
1346 int pdelay /* propagation delay (samples) */
1349 struct refclockproc *pp;
1351 char tbuf[80]; /* monitor buffer */
1352 double snr; /* on-pulse/off-pulse ratio (dB) */
1357 up = (struct wwvunit *)pp->unitptr;
1360 * Find the sample with peak energy, which defines the minute
1361 * epoch. If a sample has been found with good amplitude,
1362 * accumulate the noise squares for all except the second before
1363 * and after that position.
1365 isgood = up->epomax > STHR && up->eposnr > SSNR;
1367 fpoch = up->mphase % SECOND - up->tepoch;
1371 fpoch = pdelay + SYNSIZ;
1373 epoch = up->mphase - fpoch;
1376 if (syncx > sp->maxamp) {
1380 if (abs((epoch - sp->lastpos) % MINUTE) > SECOND)
1381 sp->noiamp += syncx;
1384 * At the end of the minute, determine the epoch of the
1385 * sync pulse, as well as the SNR and difference between
1386 * the current and previous epoch, which represents the
1387 * intrinsic frequency error plus jitter.
1389 if (up->mphase == 0) {
1390 sp->synmax = sqrt(sp->maxamp);
1391 sp->synmin = sqrt(sp->noiamp / (MINUTE - 2 * SECOND));
1392 epoch = (sp->pos - sp->lastpos) % MINUTE;
1395 * If not yet in minute sync, we have to do a little
1396 * dance to find a valid minute sync pulse, emphasis
1399 snr = wwv_snr(sp->synmax, sp->synmin);
1400 isgood = isgood && sp->synmax > ATHR && snr > ASNR;
1401 switch (sp->count) {
1404 * In state 0 the station was not heard during the
1405 * previous probe. Look for the biggest blip greater
1406 * than the amplitude threshold in the minute and assume
1407 * that the minute sync pulse. We're fishing here, since
1408 * the range gate has not yet been determined. If found,
1412 if (sp->synmax >= ATHR)
1417 * In state 1 a candidate blip has been found and the
1418 * next minute has been searched for another blip. If
1419 * none are found acceptable, drop back to state 0 and
1420 * hunt some more. Otherwise, a legitimate minute pulse
1421 * may have been found, so bump to state 2.
1432 * In states 2 and above, continue to groom samples as
1433 * before and drop back to state 0 if the groom fails.
1434 * If it succeeds, set the epoch and bump to the next
1435 * state until reaching the threshold, if ever.
1438 if (!isgood || abs(epoch) > AWND * MS) {
1442 sp->mepoch = sp->pos;
1446 if (pp->sloppyclockflag & CLK_FLAG4) {
1448 "wwv8 %d %3d %s %d %5.0f %5.1f %5ld %5d %ld",
1449 up->port, up->gain, sp->refid, sp->count,
1450 sp->synmax, snr, sp->pos, up->tepoch,
1452 record_clock_stats(&peer->srcadr, tbuf);
1455 printf("%s\n", tbuf);
1458 sp->lastpos = sp->pos;
1459 sp->maxamp = sp->noiamp = 0;
1465 * wwv_endpoc - identify and acquire second sync pulse
1467 * This routine is called at the end of the second sync interval. It
1468 * determines the second sync epoch position within the interval and
1469 * disciplines the sample clock using a frequency-lock loop (FLL).
1471 * Second sync is determined in the RF input routine as the maximum
1472 * over all 8000 samples in the second comb filter. To assure accurate
1473 * and reliable time and frequency discipline, this routine performs a
1474 * great deal of heavy-handed heuristic data filtering and grooming.
1476 * Note that, since the minute sync pulse is very wide (800 ms), precise
1477 * minute sync epoch acquisition requires at least a rough estimate of
1478 * the second sync pulse (5 ms). This becomes more important in choppy
1479 * conditions at the lower frequencies at night, since sferics and
1480 * cochannel crude can badly distort the minute pulse.
1484 struct peer *peer, /* peer structure pointer */
1485 int epopos /* epoch max position */
1488 struct refclockproc *pp;
1490 static int epoch_mf[3]; /* epoch median filter */
1491 static int xepoch; /* last second epoch */
1492 static int zepoch; /* last averaging interval epoch */
1493 static int syncnt; /* run length counter */
1494 static int maxrun; /* longest run length */
1495 static int mepoch; /* longest run epoch */
1496 static int avgcnt; /* averaging interval counter */
1497 static int avginc; /* averaging ratchet */
1498 static int iniflg; /* initialization flag */
1499 char tbuf[80]; /* monitor buffer */
1504 up = (struct wwvunit *)pp->unitptr;
1507 memset((char *)epoch_mf, 0, sizeof(epoch_mf));
1511 * A three-stage median filter is used to help denoise the
1512 * second sync pulse. The median sample becomes the candidate
1515 epoch_mf[2] = epoch_mf[1];
1516 epoch_mf[1] = epoch_mf[0];
1517 epoch_mf[0] = epopos;
1518 if (epoch_mf[0] > epoch_mf[1]) {
1519 if (epoch_mf[1] > epoch_mf[2])
1520 up->tepoch = epoch_mf[1]; /* 0 1 2 */
1521 else if (epoch_mf[2] > epoch_mf[0])
1522 up->tepoch = epoch_mf[0]; /* 2 0 1 */
1524 up->tepoch = epoch_mf[2]; /* 0 2 1 */
1526 if (epoch_mf[1] < epoch_mf[2])
1527 up->tepoch = epoch_mf[1]; /* 2 1 0 */
1528 else if (epoch_mf[2] < epoch_mf[0])
1529 up->tepoch = epoch_mf[0]; /* 1 0 2 */
1531 up->tepoch = epoch_mf[2]; /* 1 2 0 */
1535 * If the signal amplitude or SNR fall below thresholds or if no
1536 * stations are heard, dim the second sync lamp and start over.
1538 if (!(up->status & (SELV | SELH)) || up->epomax < STHR ||
1539 up->eposnr < SSNR) {
1540 up->status &= ~(SSYNC | FGATE);
1541 avgcnt = syncnt = maxrun = 0;
1547 * If the epoch candidate is the same as the last one, increment
1548 * the compare counter. If not, save the length and epoch of the
1549 * current run for use later and reset the counter.
1551 tmp2 = (up->tepoch - xepoch) % SECOND;
1555 if (maxrun > 0 && mepoch == xepoch) {
1557 } else if (syncnt > maxrun) {
1563 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & (SSYNC |
1566 "wwv1 %04x %5.0f %5.1f %5d %5d %4d %4d",
1567 up->status, up->epomax, up->eposnr, up->tepoch,
1568 tmp2, avgcnt, syncnt);
1569 record_clock_stats(&peer->srcadr, tbuf);
1572 printf("%s\n", tbuf);
1577 * The sample clock frequency is disciplined using a first order
1578 * feedback loop with time constant consistent with the Allan
1579 * intercept of typical computer clocks.
1581 * The frequency update is calculated from the epoch change in
1582 * 125-us units divided by the averaging interval in seconds.
1583 * The averaging interval affects other receiver functions,
1584 * including the the 1000/1200-Hz comb filter and codec clock
1585 * loop. It also affects the 100-Hz subcarrier loop and the bit
1586 * and digit comparison counter thresholds.
1588 if (avgcnt < up->avgint) {
1589 xepoch = up->tepoch;
1594 * During the averaging interval the longest run of identical
1595 * epoches is determined. If the longest run is at least 10
1596 * seconds, the SSYNC bit is lit and the value becomes the
1597 * reference epoch for the next interval. If not, the second
1598 * synd lamp is dark and flashers set.
1600 if (maxrun > 0 && mepoch == xepoch) {
1602 } else if (syncnt > maxrun) {
1606 xepoch = up->tepoch;
1607 if (maxrun > SCMP) {
1608 up->status |= SSYNC;
1609 up->yepoch = mepoch;
1611 up->status &= ~SSYNC;
1615 * If the epoch change over the averaging interval is less than
1616 * 1 ms, the frequency is adjusted, but clamped at +-125 PPM. If
1617 * greater than 1 ms, the counter is decremented. If the epoch
1618 * change is less than 0.5 ms, the counter is incremented. If
1619 * the counter increments to +3, the averaging interval is
1620 * doubled and the counter set to zero; if it increments to -3,
1621 * the interval is halved and the counter set to zero.
1623 * Here be spooks. From careful observations, the epoch
1624 * sometimes makes a long run of identical samples, then takes a
1625 * lurch due apparently to lost interrupts or spooks. If this
1626 * happens, the epoch change times the maximum run length will
1627 * be greater than the averaging interval, so the lurch should
1628 * be believed but the frequency left alone. Really intricate
1632 mepoch = up->tepoch;
1633 dtemp = (mepoch - zepoch) % SECOND;
1634 if (up->status & FGATE) {
1635 if (abs(dtemp) < MAXFREQ * MINAVG) {
1636 if (maxrun * abs(mepoch - zepoch) <
1638 up->freq += dtemp / avgcnt;
1639 if (up->freq > MAXFREQ)
1641 else if (up->freq < -MAXFREQ)
1642 up->freq = -MAXFREQ;
1644 if (abs(dtemp) < MAXFREQ * MINAVG / 2) {
1648 if (up->avgint < MAXAVG) {
1658 if (up->avgint > MINAVG) {
1665 if (pp->sloppyclockflag & CLK_FLAG4) {
1667 "wwv2 %04x %4.0f %4d %4d %2d %4d %4.0f %6.1f",
1668 up->status, up->epomax, mepoch, maxrun, avginc,
1669 avgcnt, dtemp, up->freq * 1e6 / SECOND);
1670 record_clock_stats(&peer->srcadr, tbuf);
1673 printf("%s\n", tbuf);
1676 up->status |= FGATE;
1678 avgcnt = syncnt = maxrun = 0;
1683 * wwv_epoch - epoch scanner
1685 * This routine scans the receiver second epoch to determine the signal
1686 * amplitudes and pulse timings. Receiver synchronization is determined
1687 * by the minute sync pulse detected in the wwv_rf() routine and the
1688 * second sync pulse detected in the wwv_epoch() routine. A pulse width
1689 * discriminator extracts data signals from the 100-Hz subcarrier. The
1690 * transmitted signals are delayed by the propagation delay, receiver
1691 * delay and filter delay of this program. Delay corrections are
1692 * introduced separately for WWV and WWVH.
1694 * Most communications radios use a highpass filter in the audio stages,
1695 * which can do nasty things to the subcarrier phase relative to the
1696 * sync pulses. Therefore, the data subcarrier reference phase is
1697 * disciplined using the hardlimited quadrature-phase signal sampled at
1698 * the same time as the in-phase signal. The phase tracking loop uses
1699 * phase adjustments of plus-minus one sample (125 us).
1703 struct peer *peer /* peer structure pointer */
1706 struct refclockproc *pp;
1709 static double dpulse; /* data pulse length */
1713 up = (struct wwvunit *)pp->unitptr;
1716 * Sample the minute sync pulse envelopes at epoch 800 for both
1717 * the WWV and WWVH stations. This will be used later for
1718 * channel and station mitigation. Note that the seconds epoch
1719 * is set here well before the end of the second to make sure we
1720 * never seet the epoch backwards.
1722 if (up->rphase == 800 * MS) {
1723 up->repoch = up->yepoch;
1724 cp = &up->mitig[up->achan];
1725 cp->wwv.synamp = cp->wwv.amp;
1726 cp->wwvh.synamp = cp->wwvh.amp;
1730 * Sample the data subcarrier at epoch 15 ms, giving a guard
1731 * time of +-15 ms from the beginning of the second until the
1732 * pulse rises at 30 ms. The I-channel amplitude is used to
1733 * calculate the slice level. The envelope amplitude is used
1734 * during the probe seconds to determine the SNR. There is a
1735 * compromise here; we want to delay the sample as long as
1736 * possible to give the radio time to change frequency and the
1737 * AGC to stabilize, but as early as possible if the second
1738 * epoch is not exact.
1740 if (up->rphase == 15 * MS) {
1741 up->noiamp = up->irig * up->irig + up->qrig * up->qrig;
1744 * Sample the data subcarrier at epoch 215 ms, giving a guard
1745 * time of +-15 ms from the earliest the pulse peak can be
1746 * reached to the earliest it can begin to fall. For the data
1747 * channel latch the I-channel amplitude for all except the
1748 * probe seconds and adjust the 100-Hz reference oscillator
1749 * phase using the Q-channel amplitude at this epoch. For the
1750 * probe channel latch the envelope amplitude.
1752 } else if (up->rphase == 215 * MS) {
1753 up->sigsig = up->irig;
1756 up->datpha = up->qrig / up->avgint;
1757 if (up->datpha >= 0) {
1759 if (up->datapt >= 80)
1766 up->sigamp = up->irig * up->irig + up->qrig * up->qrig;
1769 * The slice level is set half way between the peak signal and
1770 * noise levels. Sample the negative zero crossing after epoch
1771 * 200 ms and record the epoch at that time. This defines the
1772 * length of the data pulse, which will later be converted into
1773 * scaled bit probabilities.
1775 } else if (up->rphase > 200 * MS) {
1776 dtemp = (up->sigsig + sqrt(up->noiamp)) / 2;
1777 if (up->irig < dtemp && dpulse == 0)
1778 dpulse = up->rphase;
1782 * At the end of the second crank the clock state machine and
1783 * adjust the codec gain. Note the epoch is buffered from the
1784 * center of the second in order to avoid jitter while the
1785 * seconds synch is diddling the epoch. Then, determine the true
1786 * offset and update the median filter in the driver interface.
1788 * Sample the data subcarrier envelope at the end of the second
1789 * to determine the SNR for the pulse. This gives a guard time
1790 * of +-30 ms from the decay of the longest pulse to the rise of
1794 if (up->mphase % SECOND == up->repoch) {
1795 up->datsnr = wwv_snr(up->sigsig, sqrt(up->noiamp));
1796 wwv_rsec(peer, dpulse);
1798 up->rphase = dpulse = 0;
1804 * wwv_rsec - process receiver second
1806 * This routine is called at the end of each receiver second to
1807 * implement the per-second state machine. The machine assembles BCD
1808 * digit bits, decodes miscellaneous bits and dances the leap seconds.
1810 * Normally, the minute has 60 seconds numbered 0-59. If the leap
1811 * warning bit is set, the last minute (1439) of 30 June (day 181 or 182
1812 * for leap years) or 31 December (day 365 or 366 for leap years) is
1813 * augmented by one second numbered 60. This is accomplished by
1814 * extending the minute interval by one second and teaching the state
1815 * machine to ignore it.
1819 struct peer *peer, /* peer structure pointer */
1823 static int iniflg; /* initialization flag */
1824 static double bcddld[4]; /* BCD data bits */
1825 static double bitvec[61]; /* bit integrator for misc bits */
1826 struct refclockproc *pp;
1829 struct sync *sp, *rp;
1830 l_fp offset; /* offset in NTP seconds */
1831 double bit; /* bit likelihood */
1832 char tbuf[80]; /* monitor buffer */
1837 #endif /* IRIG_SUCKS */
1840 up = (struct wwvunit *)pp->unitptr;
1843 memset((char *)bitvec, 0, sizeof(bitvec));
1847 * The bit represents the probability of a hit on zero (negative
1848 * values), a hit on one (positive values) or a miss (zero
1849 * value). The likelihood vector is the exponential average of
1850 * these probabilities. Only the bits of this vector
1851 * corresponding to the miscellaneous bits of the timecode are
1852 * used, but it's easier to do them all. After that, crank the
1853 * seconds state machine.
1855 nsec = up->rsec + 1;
1856 bit = wwv_data(up, dpulse);
1857 bitvec[up->rsec] += (bit - bitvec[up->rsec]) / TCONST;
1858 sw = progx[up->rsec].sw;
1859 arg = progx[up->rsec].arg;
1863 * Ignore this second.
1865 case IDLE: /* 9, 45-49 */
1869 * Probe channel stuff
1871 * The WWV/H format contains data pulses in second 59 (position
1872 * identifier), second 1 (not used) and the minute sync pulse in
1873 * second 0. At the end of second 58, QSY to the probe channel,
1874 * which rotates over all WWV/H frequencies. At the end of
1875 * second 1 QSY back to the data channel.
1877 * At the end of second 0 save the minute sync pulse peak value
1878 * previously latched at 800 ms.
1881 cp = &up->mitig[up->achan];
1882 cp->wwv.synmax = sqrt(cp->wwv.synamp);
1883 cp->wwvh.synmax = sqrt(cp->wwvh.synamp);
1887 * At the end of second 1 determine the minute sync pulse
1888 * amplitude and SNR and set SYNCNG if these values are below
1889 * thresholds. Determine the data pulse amplitude and SNR and
1890 * set DATANG if these values are below thresholds. Set ERRRNG
1891 * if data pulses in second 59 and second 1 are decoded in
1892 * error. Shift a 1 into the reachability register if SYNCNG and
1893 * DATANG are both lit; otherwise shift a 0. Ignore ERRRNG for
1894 * the present. The number of 1 bits in the last six intervals
1895 * represents the channel metric used by the mitigation routine.
1896 * Finally, QSY back to the data channel.
1899 cp = &up->mitig[up->achan];
1900 cp->sigamp = sqrt(up->sigamp);
1901 cp->noiamp = sqrt(up->noiamp);
1902 cp->datsnr = wwv_snr(cp->sigamp, cp->noiamp);
1908 sp->synmin = sqrt((sp->synmin + sp->synamp) / 2.);
1909 sp->synsnr = wwv_snr(sp->synmax, sp->synmin);
1910 sp->select &= ~(SYNCNG | DATANG | ERRRNG);
1911 if (sp->synmax < QTHR || sp->synsnr < QSNR)
1912 sp->select |= SYNCNG;
1913 if (cp->sigamp < XTHR || cp->datsnr < XSNR)
1914 sp->select |= DATANG;
1916 sp->select |= ERRRNG;
1918 if (sp->reach & (1 << AMAX))
1920 if (!(sp->select & (SYNCNG | DATANG))) {
1929 rp->synmin = sqrt((rp->synmin + rp->synamp) / 2.);
1930 rp->synsnr = wwv_snr(rp->synmax, rp->synmin);
1931 rp->select &= ~(SYNCNG | DATANG | ERRRNG);
1932 if (rp->synmax < QTHR || rp->synsnr < QSNR)
1933 rp->select |= SYNCNG;
1934 if (cp->sigamp < XTHR || cp->datsnr < XSNR)
1935 rp->select |= DATANG;
1937 rp->select |= ERRRNG;
1939 if (rp->reach & (1 << AMAX))
1941 if (!(rp->select & (SYNCNG | DATANG | ERRRNG))) {
1947 * Set up for next minute.
1949 if (pp->sloppyclockflag & CLK_FLAG4) {
1951 "wwv5 %2d %04x %3d %4d %d %.0f/%.1f %s %04x %.0f %.0f/%.1f %s %04x %.0f %.0f/%.1f",
1952 up->port, up->status, up->gain, up->yepoch,
1953 up->errcnt, cp->sigamp, cp->datsnr,
1954 sp->refid, sp->reach & 0xffff,
1955 wwv_metric(sp), sp->synmax, sp->synsnr,
1956 rp->refid, rp->reach & 0xffff,
1957 wwv_metric(rp), rp->synmax, rp->synsnr);
1958 record_clock_stats(&peer->srcadr, tbuf);
1961 printf("%s\n", tbuf);
1965 if (up->fd_icom > 0)
1966 wwv_qsy(peer, up->dchan);
1968 up->status &= ~SFLAG;
1975 * Save the bit probability in the BCD data vector at the index
1976 * given by the argument. Note that all bits of the vector have
1977 * to be above the data gate threshold for the digit to be
1978 * considered valid. Bits not used in the digit are forced to
1979 * zero and not checked for errors.
1981 case COEF: /* 4-7, 10-13, 15-17, 20-23,
1982 25-26, 30-33, 35-38, 40-41,
1984 if (up->status & DGATE)
1985 up->status |= BGATE;
1989 case COEF2: /* 18, 27-28, 42-43 */
1994 * Correlate coefficient vector with each valid digit vector and
1995 * save in decoding matrix. We step through the decoding matrix
1996 * digits correlating each with the coefficients and saving the
1997 * greatest and the next lower for later SNR calculation.
1999 case DECIM2: /* 29 */
2000 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2);
2003 case DECIM3: /* 44 */
2004 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3);
2007 case DECIM6: /* 19 */
2008 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6);
2011 case DECIM9: /* 8, 14, 24, 34, 39 */
2012 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9);
2016 * Miscellaneous bits. If above the positive threshold, declare
2017 * 1; if below the negative threshold, declare 0; otherwise
2018 * raise the SYMERR alarm. At the end of second 58, QSY to the
2019 * probe channel. The design is intended to preserve the bits
2020 * over periods of signal loss.
2022 case MSC20: /* 55 */
2023 wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);
2026 case MSCBIT: /* 2-3, 50, 56-57 */
2027 if (bitvec[up->rsec] > BTHR)
2029 else if (bitvec[up->rsec] < -BTHR)
2032 up->alarm |= SYMERR;
2036 * Save the data channel gain, then QSY to the probe channel.
2038 case MSC21: /* 58 */
2039 if (bitvec[up->rsec] > BTHR)
2041 else if (bitvec[up->rsec] < -BTHR)
2044 up->alarm |= SYMERR;
2045 up->mitig[up->dchan].gain = up->gain;
2047 if (up->fd_icom > 0) {
2048 up->schan = (up->schan + 1) % NCHAN;
2049 wwv_qsy(peer, up->schan);
2052 up->status |= SFLAG | SELV | SELH;
2053 up->errbit = up->errcnt;
2060 * During second 59 the receiver and codec AGC are settling
2061 * down, so the data pulse is unusable. At the end of this
2062 * second, latch the minute sync pulse noise floor. Then do the
2063 * minute processing and update the system clock. If a leap
2064 * second sail on to the next second (60); otherwise, set up for
2068 cp = &up->mitig[up->achan];
2069 cp->wwv.synmin = cp->wwv.synamp;
2070 cp->wwvh.synmin = cp->wwvh.synamp;
2073 * Dance the leap if necessary and the kernel has the
2074 * right stuff. Then, wind up the clock and initialize
2075 * for the following minute. If the leap dance, note the
2076 * kernel is armed one second before the actual leap is
2079 if (up->status & SSYNC && up->digcnt >= 9)
2080 up->status |= INSYNC;
2081 if (up->status & LEPDAY) {
2082 pp->leap = LEAP_ADDSECOND;
2084 pp->leap = LEAP_NOWARNING;
2086 nsec = up->digcnt = 0;
2088 pp->lencode = timecode(up, pp->a_lastcode);
2089 record_clock_stats(&peer->srcadr, pp->a_lastcode);
2092 printf("wwv: timecode %d %s\n", pp->lencode,
2095 if (up->status & INSYNC && up->watch < HOLD)
2096 refclock_receive(peer);
2100 * If LEPDAY is set on the last minute of 30 June or 31
2101 * December, the LEPSEC bit is set. At the end of the minute in
2102 * which LEPSEC is set the transmitter and receiver insert an
2103 * extra second (60) in the timescale and the minute sync skips
2104 * a second. We only get to test this wrinkle at intervals of
2105 * about 18 months; the actual mileage may vary.
2109 nsec = up->digcnt = 0;
2114 * If digit sync has not been acquired before timeout or if no
2115 * station has been heard, game over and restart from scratch.
2117 if (!(up->status & DSYNC) && (!(up->status & (SELV | SELH)) ||
2118 up->watch > DIGIT)) {
2124 * If no timestamps have been struck before timeout, game over
2125 * and restart from scratch.
2127 if (up->watch > PANIC) {
2131 pp->disp += AUDIO_PHI;
2136 * You really don't wanna know what comes down here. Leave it to
2137 * say Solaris 2.8 broke the nice clean audio stream, apparently
2138 * affected by a 5-ms sawtooth jitter. Sundown on Solaris. This
2139 * leaves a little twilight.
2141 * The scheme involves differentiation, forward learning and
2142 * integration. The sawtooth has a period of 11 seconds. The
2143 * timestamp differences are integrated and subtracted from the
2146 ltemp = pp->lastrec;
2147 L_SUB(<emp, &pp->lastref);
2152 pp->lastref = pp->lastrec;
2153 if (!L_ISNEG(<emp))
2156 L_ADD(&up->wigwag, <emp);
2157 L_SUB(&pp->lastrec, &up->wigwag);
2158 up->wiggle[up->wp] = ltemp;
2161 * Bottom fisher. To understand this, you have to know about
2162 * velocity microphones and AM transmitters. No further
2163 * explanation is offered, as this is truly a black art.
2165 up->wigbot[up->wp] = pp->lastrec;
2166 for (i = 0; i < WIGGLE; i++) {
2168 up->wigbot[i].l_ui++;
2169 L_SUB(&pp->lastrec, &up->wigbot[i]);
2170 if (L_ISNEG(&pp->lastrec))
2171 L_ADD(&pp->lastrec, &up->wigbot[i]);
2173 pp->lastrec = up->wigbot[i];
2177 #endif /* IRIG_SUCKS */
2180 * If victory has been declared and seconds sync is lit, strike
2181 * a timestamp. It should not be a surprise, especially if the
2182 * radio is not tunable, that sometimes no stations are above
2183 * the noise and the reference ID set to NONE.
2185 if (up->status & INSYNC && up->status & SSYNC) {
2186 pp->second = up->rsec;
2187 pp->minute = up->decvec[MN].digit + up->decvec[MN +
2189 pp->hour = up->decvec[HR].digit + up->decvec[HR +
2191 pp->day = up->decvec[DA].digit + up->decvec[DA +
2192 1].digit * 10 + up->decvec[DA + 2].digit * 100;
2193 pp->year = up->decvec[YR].digit + up->decvec[YR +
2197 if (!clocktime(pp->day, pp->hour, pp->minute,
2198 pp->second, GMT, up->timestamp.l_ui,
2199 &pp->yearstart, &offset.l_ui)) {
2200 up->errflg = CEVNT_BADTIME;
2204 refclock_process_offset(pp, offset,
2205 up->timestamp, PDELAY);
2208 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
2211 "wwv3 %2d %04x %5.0f %5.1f %5.0f %5.1f %5.0f",
2212 up->rsec, up->status, up->epomax, up->eposnr,
2213 up->sigsig, up->datsnr, bit);
2214 record_clock_stats(&peer->srcadr, tbuf);
2217 printf("%s\n", tbuf);
2224 * wwv_data - calculate bit probability
2226 * This routine is called at the end of the receiver second to calculate
2227 * the probabilities that the previous second contained a zero (P0), one
2228 * (P1) or position indicator (P2) pulse. If not in sync or if the data
2229 * bit is bad, a bit error is declared and the probabilities are forced
2230 * to zero. Otherwise, the data gate is enabled and the probabilities
2231 * are calculated. Note that the data matched filter contributes half
2232 * the pulse width, or 85 ms.
2234 * It's important to observe that there are three conditions to
2235 * determine: average to +1 (hit), average to -1 (miss) or average to
2236 * zero (erasure). The erasure condition results from insufficient
2237 * signal (noise) and has no bias toward either a hit or miss.
2241 struct wwvunit *up, /* driver unit pointer */
2242 double pulse /* pulse length (sample units) */
2245 double p0, p1, p2; /* probabilities */
2246 double dpulse; /* pulse length in ms */
2249 dpulse = pulse - DATSIZ / 2;
2252 * If no station is being tracked, if either the data amplitude
2253 * or SNR are below threshold or if the pulse length is less
2254 * than 170 ms, declare an erasure.
2256 if (!(up->status & (SELV | SELH)) || up->sigsig < DTHR ||
2257 up->datsnr < DSNR || dpulse < DATSIZ) {
2258 up->status |= DGATE;
2260 if (up->errcnt > MAXERR)
2261 up->alarm |= MODERR;
2266 * The probability of P0 is one below 200 ms falling to zero at
2267 * 500 ms. The probability of P1 is zero below 200 ms rising to
2268 * one at 500 ms and falling to zero at 800 ms. The probability
2269 * of P2 is zero below 500 ms, rising to one above 800 ms.
2271 up->status &= ~DGATE;
2272 if (dpulse < (200 * MS)) {
2274 } else if (dpulse < 500 * MS) {
2276 p1 = dpulse / (300 * MS);
2278 } else if (dpulse < 800 * MS) {
2280 p2 = dpulse / (300 * MS);
2287 * The ouput is a metric that ranges from -1 (P0), to +1 (P1)
2288 * scaled for convenience. An output of zero represents an
2289 * erasure, either because of a data error or pulse length
2290 * greater than 500 ms. At the moment, we don't use P2.
2292 return ((p1 - p0) * MAXSIG);
2297 * wwv_corr4 - determine maximum likelihood digit
2299 * This routine correlates the received digit vector with the BCD
2300 * coefficient vectors corresponding to all valid digits at the given
2301 * position in the decoding matrix. The maximum value corresponds to the
2302 * maximum likelihood digit, while the ratio of this value to the next
2303 * lower value determines the likelihood function. Note that, if the
2304 * digit is invalid, the likelihood vector is averaged toward a miss.
2308 struct peer *peer, /* peer unit pointer */
2309 struct decvec *vp, /* decoding table pointer */
2310 double data[], /* received data vector */
2311 double tab[][4] /* correlation vector array */
2314 struct refclockproc *pp;
2317 double topmax, nxtmax; /* metrics */
2318 double acc; /* accumulator */
2319 char tbuf[80]; /* monitor buffer */
2320 int mldigit; /* max likelihood digit */
2321 int diff; /* decoding difference */
2325 up = (struct wwvunit *)pp->unitptr;
2328 * Correlate digit vector with each BCD coefficient vector. If
2329 * any BCD digit bit is bad, consider all bits a miss.
2332 topmax = nxtmax = -MAXSIG;
2333 for (i = 0; tab[i][0] != 0; i++) {
2335 for (j = 0; j < 4; j++) {
2336 if (!(up->status & BGATE))
2337 acc += data[j] * tab[i][j];
2339 acc = (vp->like[i] += (acc - vp->like[i]) / TCONST);
2344 } else if (acc > nxtmax) {
2348 vp->mldigit = mldigit;
2349 vp->digprb = topmax;
2350 vp->digsnr = wwv_snr(topmax, nxtmax);
2353 * The maximum likelihood digit is compared with the current
2354 * clock digit. The difference represents the decoding phase
2355 * error. If the clock is not yet synchronized, the phase error
2356 * is corrected even of the digit probability and likelihood are
2357 * below thresholds. This avoids lengthy averaging times should
2358 * a carry mistake occur. However, the digit is not declared
2359 * synchronized until these values are above thresholds and the
2360 * last five decoded values are identical. If the clock is
2361 * synchronized, the phase error is not corrected unless the
2362 * last five digits are all above thresholds and identical. This
2363 * avoids mistakes when the signal is coming out of the noise
2364 * and the SNR is very marginal.
2366 diff = mldigit - vp->digit;
2369 if (diff != vp->phase) {
2373 if (vp->digsnr < BSNR) {
2375 up->alarm |= SYMERR;
2376 } else if (vp->digprb < BTHR) {
2378 up->alarm |= SYMERR;
2379 if (!(up->status & INSYNC)) {
2381 vp->digit = mldigit;
2383 } else if (vp->count < BCMP) {
2385 up->status |= DSYNC;
2386 if (!(up->status & INSYNC)) {
2388 vp->digit = mldigit;
2392 vp->digit = mldigit;
2395 if (vp->digit != mldigit)
2396 up->alarm |= DECERR;
2397 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
2400 "wwv4 %2d %04x %5.0f %2d %d %d %d %d %5.0f %5.1f",
2401 up->rsec, up->status, up->epomax, vp->radix,
2402 vp->digit, vp->mldigit, vp->phase, vp->count,
2403 vp->digprb, vp->digsnr);
2404 record_clock_stats(&peer->srcadr, tbuf);
2407 printf("%s\n", tbuf);
2410 up->status &= ~BGATE;
2415 * wwv_tsec - transmitter minute processing
2417 * This routine is called at the end of the transmitter minute. It
2418 * implements a state machine that advances the logical clock subject to
2419 * the funny rules that govern the conventional clock and calendar.
2423 struct wwvunit *up /* driver structure pointer */
2426 int minute, day, isleap;
2430 * Advance minute unit of the day.
2432 temp = carry(&up->decvec[MN]); /* minute units */
2435 * Propagate carries through the day.
2437 if (temp == 0) /* carry minutes */
2438 temp = carry(&up->decvec[MN + 1]);
2439 if (temp == 0) /* carry hours */
2440 temp = carry(&up->decvec[HR]);
2442 temp = carry(&up->decvec[HR + 1]);
2445 * Decode the current minute and day. Set leap day if the
2446 * timecode leap bit is set on 30 June or 31 December. Set leap
2447 * minute if the last minute on leap day. This code fails in
2450 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit *
2451 10 + up->decvec[HR].digit * 60 + up->decvec[HR +
2453 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
2454 up->decvec[DA + 2].digit * 100;
2455 isleap = (up->decvec[YR].digit & 0x3) == 0;
2456 if (up->misc & SECWAR && (day == (isleap ? 182 : 183) || day ==
2457 (isleap ? 365 : 366)) && up->status & INSYNC && up->status &
2459 up->status |= LEPDAY;
2461 up->status &= ~LEPDAY;
2462 if (up->status & LEPDAY && minute == 1439)
2463 up->status |= LEPSEC;
2465 up->status &= ~LEPSEC;
2468 * Roll the day if this the first minute and propagate carries
2474 while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */
2475 while (carry(&up->decvec[HR + 1]) != 0);
2477 temp = carry(&up->decvec[DA]); /* carry days */
2479 temp = carry(&up->decvec[DA + 1]);
2481 temp = carry(&up->decvec[DA + 2]);
2484 * Roll the year if this the first day and propagate carries
2485 * through the century.
2487 if (day != (isleap ? 365 : 366))
2490 while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */
2491 while (carry(&up->decvec[DA + 1]) != 0);
2492 while (carry(&up->decvec[DA + 2]) != 0);
2493 temp = carry(&up->decvec[YR]); /* carry years */
2495 carry(&up->decvec[YR + 1]);
2500 * carry - process digit
2502 * This routine rotates a likelihood vector one position and increments
2503 * the clock digit modulo the radix. It returns the new clock digit or
2504 * zero if a carry occurred. Once synchronized, the clock digit will
2505 * match the maximum likelihood digit corresponding to that position.
2509 struct decvec *dp /* decoding table pointer */
2515 dp->digit++; /* advance clock digit */
2516 if (dp->digit == dp->radix) { /* modulo radix */
2519 temp = dp->like[dp->radix - 1]; /* rotate likelihood vector */
2520 for (j = dp->radix - 1; j > 0; j--)
2521 dp->like[j] = dp->like[j - 1];
2528 * wwv_snr - compute SNR or likelihood function
2532 double signal, /* signal */
2533 double noise /* noise */
2539 * This is a little tricky. Due to the way things are measured,
2540 * either or both the signal or noise amplitude can be negative
2541 * or zero. The intent is that, if the signal is negative or
2542 * zero, the SNR must always be zero. This can happen with the
2543 * subcarrier SNR before the phase has been aligned. On the
2544 * other hand, in the likelihood function the "noise" is the
2545 * next maximum down from the peak and this could be negative.
2546 * However, in this case the SNR is truly stupendous, so we
2547 * simply cap at MAXSNR dB.
2551 } else if (noise <= 0) {
2554 rval = 20 * log10(signal / noise);
2563 * wwv_newchan - change to new data channel
2565 * The radio actually appears to have ten channels, one channel for each
2566 * of five frequencies and each of two stations (WWV and WWVH), although
2567 * if not tunable only the 15 MHz channels appear live. While the radio
2568 * is tuned to the working data channel frequency and station for most
2569 * of the minute, during seconds 59, 0 and 1 the radio is tuned to a
2570 * probe frequency in order to search for minute sync pulse and data
2571 * subcarrier from other transmitters.
2573 * The search for WWV and WWVH operates simultaneously, with WWV minute
2574 * sync pulse at 1000 Hz and WWVH at 1200 Hz. The probe frequency
2575 * rotates each minute over 2.5, 5, 10, 15 and 20 MHz in order and yes,
2576 * we all know WWVH is dark on 20 MHz, but few remember when WWV was lit
2579 * This routine selects the best channel using a metric computed from
2580 * the reachability register and minute pulse amplitude. Normally, the
2581 * award goes to the the channel with the highest metric; but, in case
2582 * of ties, the award goes to the channel with the highest minute sync
2583 * pulse amplitude and then to the highest frequency.
2585 * The routine performs an important squelch function to keep dirty data
2586 * from polluting the integrators. During acquisition and until the
2587 * clock is synchronized, the signal metric must be at least MTR (13);
2588 * after that the metrict must be at least TTHR (50). If either of these
2589 * is not true, the station select bits are cleared so the second sync
2590 * is disabled and the data bit integrators averaged to a miss.
2594 struct peer *peer /* peer structure pointer */
2597 struct refclockproc *pp;
2599 struct sync *sp, *rp;
2604 up = (struct wwvunit *)pp->unitptr;
2607 * Search all five station pairs looking for the channel with
2608 * maximum metric. If no station is found above thresholds, the
2609 * reference ID is set to NONE and we wait for hotter ions.
2614 for (i = 0; i < NCHAN; i++) {
2615 rp = &up->mitig[i].wwvh;
2616 dtemp = wwv_metric(rp);
2617 if (dtemp >= rank) {
2622 rp = &up->mitig[i].wwv;
2623 dtemp = wwv_metric(rp);
2624 if (dtemp >= rank) {
2632 up->status &= ~(SELV | SELH);
2633 memcpy(&pp->refid, "NONE", 4);
2634 if ((!(up->status & INSYNC) && rank >= MTHR) || ((up->status &
2635 INSYNC) && rank >= TTHR)) {
2636 up->status |= sp->select & (SELV | SELH);
2637 memcpy(&pp->refid, sp->refid, 4);
2639 if (peer->stratum <= 1)
2640 memcpy(&peer->refid, &pp->refid, 4);
2645 * www_newgame - reset and start over
2649 struct peer *peer /* peer structure pointer */
2652 struct refclockproc *pp;
2658 up = (struct wwvunit *)pp->unitptr;
2661 * Initialize strategic values. Note we set the leap bits
2662 * NOTINSYNC and the refid "NONE".
2664 peer->leap = LEAP_NOTINSYNC;
2665 up->watch = up->status = up->alarm = 0;
2666 up->avgint = MINAVG;
2669 up->gain = MAXGAIN / 2;
2672 * Initialize the station processes for audio gain, select bit,
2673 * station/frequency identifier and reference identifier.
2675 memset(up->mitig, 0, sizeof(up->mitig));
2676 for (i = 0; i < NCHAN; i++) {
2678 cp->gain = up->gain;
2679 cp->wwv.select = SELV;
2680 sprintf(cp->wwv.refid, "WV%.0f", floor(qsy[i]));
2681 cp->wwvh.select = SELH;
2682 sprintf(cp->wwvh.refid, "WH%.0f", floor(qsy[i]));
2688 * wwv_metric - compute station metric
2690 * The most significant bits represent the number of ones in the
2691 * reachability register. The least significant bits represent the
2692 * minute sync pulse amplitude. The combined value is scaled 0-100.
2696 struct sync *sp /* station pointer */
2701 dtemp = sp->count * MAXSIG;
2702 if (sp->synmax < MAXSIG)
2703 dtemp += sp->synmax;
2705 dtemp += MAXSIG - 1;
2706 dtemp /= (AMAX + 1) * MAXSIG;
2707 return (dtemp * 100.);
2713 * wwv_qsy - Tune ICOM receiver
2715 * This routine saves the AGC for the current channel, switches to a new
2716 * channel and restores the AGC for that channel. If a tunable receiver
2717 * is not available, just fake it.
2721 struct peer *peer, /* peer structure pointer */
2722 int chan /* channel */
2726 struct refclockproc *pp;
2730 up = (struct wwvunit *)pp->unitptr;
2731 if (up->fd_icom > 0) {
2732 up->mitig[up->achan].gain = up->gain;
2733 rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
2736 up->gain = up->mitig[up->achan].gain;
2744 * timecode - assemble timecode string and length
2746 * Prettytime format - similar to Spectracom
2748 * sq yy ddd hh:mm:ss ld dut lset agc iden sig errs freq avgt
2750 * s sync indicator ('?' or ' ')
2751 * q error bits (hex 0-F)
2752 * yyyy year of century
2756 * ss second of minute)
2757 * l leap second warning (' ' or 'L')
2758 * d DST state ('S', 'D', 'I', or 'O')
2759 * dut DUT sign and magnitude (0.1 s)
2760 * lset minutes since last clock update
2761 * agc audio gain (0-255)
2762 * iden reference identifier (station and frequency)
2763 * sig signal quality (0-100)
2764 * errs bit errors in last minute
2765 * freq frequency offset (PPM)
2766 * avgt averaging time (s)
2770 struct wwvunit *up, /* driver structure pointer */
2771 char *ptr /* target string */
2775 int year, day, hour, minute, second, dut;
2776 char synchar, leapchar, dst;
2781 * Common fixed-format fields
2783 synchar = (up->status & INSYNC) ? ' ' : '?';
2784 year = up->decvec[YR].digit + up->decvec[YR + 1].digit * 10 +
2786 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
2787 up->decvec[DA + 2].digit * 100;
2788 hour = up->decvec[HR].digit + up->decvec[HR + 1].digit * 10;
2789 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * 10;
2791 leapchar = (up->misc & SECWAR) ? 'L' : ' ';
2792 dst = dstcod[(up->misc >> 4) & 0x3];
2793 dut = up->misc & 0x7;
2794 if (!(up->misc & DUTS))
2796 sprintf(ptr, "%c%1X", synchar, up->alarm);
2797 sprintf(cptr, " %4d %03d %02d:%02d:%02d %c%c %+d",
2798 year, day, hour, minute, second, leapchar, dst, dut);
2802 * Specific variable-format fields
2805 sprintf(cptr, " %d %d %s %.0f %d %.1f %d", up->watch,
2806 up->mitig[up->dchan].gain, sp->refid, wwv_metric(sp),
2807 up->errbit, up->freq / SECOND * 1e6, up->avgint);
2809 return (strlen(ptr));
2814 * wwv_gain - adjust codec gain
2816 * This routine is called at the end of each second. It counts the
2817 * number of signal clips above the MAXSIG threshold during the previous
2818 * second. If there are no clips, the gain is bumped up; if too many
2819 * clips, it is bumped down. The decoder is relatively insensitive to
2820 * amplitude, so this crudity works just fine. The input port is set and
2821 * the error flag is cleared, mostly to be ornery.
2825 struct peer *peer /* peer structure pointer */
2828 struct refclockproc *pp;
2832 up = (struct wwvunit *)pp->unitptr;
2835 * Apparently, the codec uses only the high order bits of the
2836 * gain control field. Thus, it may take awhile for changes to
2837 * wiggle the hardware bits.
2839 if (up->clipcnt == 0) {
2841 if (up->gain > MAXGAIN)
2843 } else if (up->clipcnt > MAXCLP) {
2848 audio_gain(up->gain, up->mongain, up->port);
2858 int refclock_wwv_bs;
2859 #endif /* REFCLOCK */