📄 refclock_wwv.c
字号:
/* * refclock_wwv - clock driver for NIST WWV/H time/frequency station */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_WWV)#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_calendar.h"#include "ntp_stdlib.h"#include "audio.h"#include <stdio.h>#include <ctype.h>#include <math.h>#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif /* HAVE_SYS_IOCTL_H */#define ICOM 1#ifdef ICOM#include "icom.h"#endif /* ICOM *//* * Audio WWV/H demodulator/decoder * * This driver synchronizes the computer time using data encoded in * radio transmissions from NIST time/frequency stations WWV in Boulder, * CO, and WWVH in Kauai, HI. Transmissions are made continuously on * 2.5, 5, 10, 15 and 20 MHz in AM mode. An ordinary shortwave receiver * can be tuned manually to one of these frequencies or, in the case of * ICOM receivers, the receiver can be tuned automatically using this * program as propagation conditions change throughout the day and * night. * * The driver receives, demodulates and decodes the radio signals when * connected to the audio codec of a workstation running Solaris, SunOS * FreeBSD or Linux, and with a little help, other workstations with * similar codecs or sound cards. In this implementation, only one audio * driver and codec can be supported on a single machine. * * The demodulation and decoding algorithms used in this driver are * based on those developed for the TAPR DSP93 development board and the * TI 320C25 digital signal processor described in: Mills, D.L. A * precision radio clock for WWV transmissions. Electrical Engineering * Report 97-8-1, University of Delaware, August 1997, 25 pp., available * from www.eecis.udel.edu/~mills/reports.htm. The algorithms described * in this report have been modified somewhat to improve performance * under weak signal conditions and to provide an automatic station * identification feature. * * The ICOM code is normally compiled in the driver. It isn't used, * unless the mode keyword on the server configuration command specifies * a nonzero ICOM ID select code. The C-IV trace is turned on if the * debug level is greater than one. * * Fudge factors * * Fudge flag4 causes the dubugging output described above to be * recorded in the clockstats file. Fudge flag2 selects the audio input * port, where 0 is the mike port (default) and 1 is the line-in port. * It does not seem useful to select the compact disc player port. Fudge * flag3 enables audio monitoring of the input signal. For this purpose, * the monitor gain is set to a default value. Fudgetime2 is used as a * frequency vernier for broken codec sample frequency. *//* * General definitions. Note the DGAIN parameter might need to be * changed to fit the audio response of the radio at 100 Hz. The * WWV/WWVH data subcarrier is transmitted at 10 dB down from 100 * percent modulation; however, the matched filter boosts it by a factor * of 17 and the receiver bandpass does what it does. The compromise * value here is five. Your milege may vary.. */#define DEVICE_AUDIO "/dev/audio" /* audio device name */#define AUDIO_BUFSIZ 320 /* audio buffer size (50 ms) */#define PRECISION (-10) /* precision assumed (about 1 ms) */#define DESCRIPTION "WWV/H Audio Demodulator/Decoder" /* WRU */#define SECOND 8000 /* second epoch (sample rate) (Hz) */#define MINUTE (SECOND * 60) /* minute epoch */#define OFFSET 128 /* companded sample offset */#define SIZE 256 /* decompanding table size */#define MAXSIG 6000. /* max signal level reference */#define MAXCLP 100 /* max clips above reference per s */#define MAXSNR 40. /* max SNR reference */#define MAXFREQ 1.5 /* max frequency tolerance (187 PPM) */#define DATCYC 170 /* data filter cycles */#define DATSIZ (DATCYC * MS) /* data filter size */#define SYNCYC 800 /* minute filter cycles */#define SYNSIZ (SYNCYC * MS) /* minute filter size */#define TCKCYC 5 /* tick filter cycles */#define TCKSIZ (TCKCYC * MS) /* tick filter size */#define NCHAN 5 /* number of radio channels */#define DCHAN 3 /* default radio channel (15 Mhz) */#define AUDIO_PHI 5e-6 /* dispersion growth factor */#define DGAIN 5. /* subcarrier gain *//* * General purpose status bits (status) * * SELV and/or SELH are set when WWV or WWVH has been heard and cleared * on signal loss. SSYNC is set when the second sync pulse has been * acquired and cleared by signal loss. MSYNC is set when the minute * sync pulse has been acquired. DSYNC is set when the units digit has * has reached the threshold and INSYNC is set when all nine digits have * reached the threshold. The MSYNC, DSYNC and INSYNC bits are cleared * only by timeout, upon which the driver starts over from scratch. * * DGATE is lit if the data bit amplitude or SNR is below thresholds and * BGATE is lit if a the pulse width amplitude or SNR is below * thresolds. LEPSEC is set during the last minute of the leap day At * the end of this minute the driver inserts second 60 in the seconds * state machine and the minute sync slips a second. */#define MSYNC 0x0001 /* minute epoch sync */#define SSYNC 0x0002 /* second epoch sync */#define DSYNC 0x0004 /* minute units sync */#define INSYNC 0x0008 /* clock synchronized */#define FGATE 0x0010 /* frequency gate */#define DGATE 0x0020 /* data pulse amplitude error */#define BGATE 0x0040 /* data pulse width error */#define LEPSEC 0x1000 /* leap minute *//* * Station scoreboard bits * * These are used to establish the signal quality for each of the five * frequencies and two stations. */#define SELV 0x0100 /* WWV station select */#define SELH 0x0200 /* WWVH station select *//* * Alarm status bits (alarm) * * These bits indicate various alarm conditions, which are decoded to * form the quality character included in the timecode. */#define CMPERR 1 /* BCD digit compare error */#define LOWERR 2 /* low bit or digit amplitude or SNR */#define NINERR 4 /* less than nine digits in minute */#define SYNERR 8 /* not tracking second sync *//* * Watchcat timeouts (watch) * * If these timeouts expire, the status bits are mashed to zero and the * driver starts from scratch. Suitably more refined procedures may be * developed in future. All these are in minutes. */#define ACQSN 5 /* station acquisition timeout */#define DATA 10 /* unit minutes timeout */#define SYNCH 30 /* station sync timeout */#define PANIC (2 * 1440) /* panic timeout *//* * Thresholds. These establish the minimum signal level, minimum SNR and * maximum jitter thresholds which establish the error and false alarm * rates of the driver. The values defined here may be on the * adventurous side in the interest of the highest sensitivity. */#define MTHR 13. /* acquisition signal gate (percent) */#define TTHR 50. /* tracking signal gate (percent) */#define AWND 20 /* acquisition jitter threshold (ms) */#define ATHR 3000. /* QRZ minute sync threshold */#define ASNR 20. /* QRZ minute sync SNR threshold (dB) */#define QTHR 3000. /* QSY minute sync threshold */#define QSNR 20. /* QSY minute sync SNR threshold (dB) */#define STHR 3000. /* second sync threshold */#define SSNR 15. /* second sync SNR threshold (dB) */#define SCMP 10 /* second sync compare threshold */#define DTHR 1000. /* bit threshold */#define DSNR 10. /* bit SNR threshold (dB) */#define AMIN 3 /* min bit count */#define AMAX 6 /* max bit count */#define BTHR 1000. /* digit threshold */#define BSNR 3. /* digit likelihood threshold (dB) */#define BCMP 3 /* digit compare threshold */#define MAXERR 20 /* maximum error alarm *//* * Tone frequency definitions. The increments are for 4.5-deg sine * table. */#define MS (SECOND / 1000) /* samples per millisecond */#define IN100 ((100 * 80) / SECOND) /* 100 Hz increment */#define IN1000 ((1000 * 80) / SECOND) /* 1000 Hz increment */#define IN1200 ((1200 * 80) / SECOND) /* 1200 Hz increment *//* * Acquisition and tracking time constants */#define MINAVG 8 /* min averaging time */#define MAXAVG 1024 /* max averaging time */#define FCONST 3 /* frequency time constant */#define TCONST 16 /* data bit/digit time constant *//* * Miscellaneous status bits (misc) * * These bits correspond to designated bits in the WWV/H timecode. The * bit probabilities are exponentially averaged over several minutes and * processed by a integrator and threshold. */#define DUT1 0x01 /* 56 DUT .1 */#define DUT2 0x02 /* 57 DUT .2 */#define DUT4 0x04 /* 58 DUT .4 */#define DUTS 0x08 /* 50 DUT sign */#define DST1 0x10 /* 55 DST1 leap warning */#define DST2 0x20 /* 2 DST2 DST1 delayed one day */#define SECWAR 0x40 /* 3 leap second warning *//* * The on-time synchronization point for the driver is the second epoch * sync pulse produced by the FIR matched filters. As the 5-ms delay of * these filters is compensated, the program delay is 1.1 ms due to the * 600-Hz IIR bandpass filter. The measured receiver delay is 4.7 ms and * the codec delay less than 0.2 ms. The additional propagation delay * specific to each receiver location can be programmed in the fudge * time1 and time2 values for WWV and WWVH, respectively. */#define PDELAY (.0011 + .0047 + .0002) /* net system delay (s) *//* * Table of sine values at 4.5-degree increments. This is used by the * synchronous matched filter demodulators. */double sintab[] = { 0.000000e+00, 7.845910e-02, 1.564345e-01, 2.334454e-01, /* 0-3 */ 3.090170e-01, 3.826834e-01, 4.539905e-01, 5.224986e-01, /* 4-7 */ 5.877853e-01, 6.494480e-01, 7.071068e-01, 7.604060e-01, /* 8-11 */ 8.090170e-01, 8.526402e-01, 8.910065e-01, 9.238795e-01, /* 12-15 */ 9.510565e-01, 9.723699e-01, 9.876883e-01, 9.969173e-01, /* 16-19 */ 1.000000e+00, 9.969173e-01, 9.876883e-01, 9.723699e-01, /* 20-23 */ 9.510565e-01, 9.238795e-01, 8.910065e-01, 8.526402e-01, /* 24-27 */ 8.090170e-01, 7.604060e-01, 7.071068e-01, 6.494480e-01, /* 28-31 */ 5.877853e-01, 5.224986e-01, 4.539905e-01, 3.826834e-01, /* 32-35 */ 3.090170e-01, 2.334454e-01, 1.564345e-01, 7.845910e-02, /* 36-39 */-0.000000e+00, -7.845910e-02, -1.564345e-01, -2.334454e-01, /* 40-43 */-3.090170e-01, -3.826834e-01, -4.539905e-01, -5.224986e-01, /* 44-47 */-5.877853e-01, -6.494480e-01, -7.071068e-01, -7.604060e-01, /* 48-51 */-8.090170e-01, -8.526402e-01, -8.910065e-01, -9.238795e-01, /* 52-55 */-9.510565e-01, -9.723699e-01, -9.876883e-01, -9.969173e-01, /* 56-59 */-1.000000e+00, -9.969173e-01, -9.876883e-01, -9.723699e-01, /* 60-63 */-9.510565e-01, -9.238795e-01, -8.910065e-01, -8.526402e-01, /* 64-67 */-8.090170e-01, -7.604060e-01, -7.071068e-01, -6.494480e-01, /* 68-71 */-5.877853e-01, -5.224986e-01, -4.539905e-01, -3.826834e-01, /* 72-75 */-3.090170e-01, -2.334454e-01, -1.564345e-01, -7.845910e-02, /* 76-79 */ 0.000000e+00}; /* 80 *//* * Decoder operations at the end of each second are driven by a state * machine. The transition matrix consists of a dispatch table indexed * by second number. Each entry in the table contains a case switch * number and argument. */struct progx { int sw; /* case switch number */ int arg; /* argument */};/* * Case switch numbers */#define IDLE 0 /* no operation */#define COEF 1 /* BCD bit */#define COEF1 2 /* BCD bit for minute unit */#define COEF2 3 /* BCD bit not used */#define DECIM9 4 /* BCD digit 0-9 */#define DECIM6 5 /* BCD digit 0-6 */#define DECIM3 6 /* BCD digit 0-3 */#define DECIM2 7 /* BCD digit 0-2 */#define MSCBIT 8 /* miscellaneous bit */#define MSC20 9 /* miscellaneous bit */ #define MSC21 10 /* QSY probe channel */ #define MIN1 11 /* latch time */ #define MIN2 12 /* leap second */#define SYNC2 13 /* latch minute sync pulse */ #define SYNC3 14 /* latch data pulse */ /* * Offsets in decoding matrix */#define MN 0 /* minute digits (2) */#define HR 2 /* hour digits (2) */#define DA 4 /* day digits (3) */#define YR 7 /* year digits (2) */struct progx progx[] = { {SYNC2, 0}, /* 0 latch minute sync pulse */ {SYNC3, 0}, /* 1 latch data pulse */ {MSCBIT, DST2}, /* 2 dst2 */ {MSCBIT, SECWAR}, /* 3 lw */ {COEF, 0}, /* 4 1 year units */ {COEF, 1}, /* 5 2 */ {COEF, 2}, /* 6 4 */ {COEF, 3}, /* 7 8 */ {DECIM9, YR}, /* 8 */ {IDLE, 0}, /* 9 p1 */ {COEF1, 0}, /* 10 1 minute units */ {COEF1, 1}, /* 11 2 */ {COEF1, 2}, /* 12 4 */ {COEF1, 3}, /* 13 8 */ {DECIM9, MN}, /* 14 */ {COEF, 0}, /* 15 10 minute tens */ {COEF, 1}, /* 16 20 */ {COEF, 2}, /* 17 40 */ {COEF2, 3}, /* 18 80 (not used) */ {DECIM6, MN + 1}, /* 19 p2 */ {COEF, 0}, /* 20 1 hour units */ {COEF, 1}, /* 21 2 */ {COEF, 2}, /* 22 4 */ {COEF, 3}, /* 23 8 */ {DECIM9, HR}, /* 24 */ {COEF, 0}, /* 25 10 hour tens */ {COEF, 1}, /* 26 20 */ {COEF2, 2}, /* 27 40 (not used) */ {COEF2, 3}, /* 28 80 (not used) */ {DECIM2, HR + 1}, /* 29 p3 */ {COEF, 0}, /* 30 1 day units */ {COEF, 1}, /* 31 2 */ {COEF, 2}, /* 32 4 */ {COEF, 3}, /* 33 8 */ {DECIM9, DA}, /* 34 */ {COEF, 0}, /* 35 10 day tens */ {COEF, 1}, /* 36 20 */ {COEF, 2}, /* 37 40 */ {COEF, 3}, /* 38 80 */ {DECIM9, DA + 1}, /* 39 p4 */ {COEF, 0}, /* 40 100 day hundreds */ {COEF, 1}, /* 41 200 */ {COEF2, 2}, /* 42 400 (not used) */ {COEF2, 3}, /* 43 800 (not used) */ {DECIM3, DA + 2}, /* 44 */ {IDLE, 0}, /* 45 */ {IDLE, 0}, /* 46 */ {IDLE, 0}, /* 47 */ {IDLE, 0}, /* 48 */ {IDLE, 0}, /* 49 p5 */ {MSCBIT, DUTS}, /* 50 dut+- */ {COEF, 0}, /* 51 10 year tens */ {COEF, 1}, /* 52 20 */ {COEF, 2}, /* 53 40 */ {COEF, 3}, /* 54 80 */ {MSC20, DST1}, /* 55 dst1 */ {MSCBIT, DUT1}, /* 56 0.1 dut */ {MSCBIT, DUT2}, /* 57 0.2 */ {MSC21, DUT4}, /* 58 0.4 QSY probe channel */ {MIN1, 0}, /* 59 p6 latch time */ {MIN2, 0} /* 60 leap second */};/* * BCD coefficients for maximum likelihood digit decode */#define P15 1. /* max positive number */#define N15 -1. /* max negative number *//* * Digits 0-9 */#define P9 (P15 / 4) /* mark (+1) */#define N9 (N15 / 4) /* space (-1) */double bcd9[][4] = { {N9, N9, N9, N9}, /* 0 */ {P9, N9, N9, N9}, /* 1 */ {N9, P9, N9, N9}, /* 2 */ {P9, P9, N9, N9}, /* 3 */ {N9, N9, P9, N9}, /* 4 */ {P9, N9, P9, N9}, /* 5 */ {N9, P9, P9, N9}, /* 6 */ {P9, P9, P9, N9}, /* 7 */ {N9, N9, N9, P9}, /* 8 */ {P9, N9, N9, P9}, /* 9 */ {0, 0, 0, 0} /* backstop */};/* * Digits 0-6 (minute tens) */#define P6 (P15 / 3) /* mark (+1) */#define N6 (N15 / 3) /* space (-1) */double bcd6[][4] = { {N6, N6, N6, 0}, /* 0 */ {P6, N6, N6, 0}, /* 1 */ {N6, P6, N6, 0}, /* 2 */ {P6, P6, N6, 0}, /* 3 */ {N6, N6, P6, 0}, /* 4 */ {P6, N6, P6, 0}, /* 5 */ {N6, P6, P6, 0}, /* 6 */ {0, 0, 0, 0} /* backstop */};/* * Digits 0-3 (day hundreds) */#define P3 (P15 / 2) /* mark (+1) */#define N3 (N15 / 2) /* space (-1) */double bcd3[][4] = { {N3, N3, 0, 0}, /* 0 */ {P3, N3, 0, 0}, /* 1 */ {N3, P3, 0, 0}, /* 2 */ {P3, P3, 0, 0}, /* 3 */ {0, 0, 0, 0} /* backstop */};/* * Digits 0-2 (hour tens) */#define P2 (P15 / 2) /* mark (+1) */#define N2 (N15 / 2) /* space (-1) */double bcd2[][4] = { {N2, N2, 0, 0}, /* 0 */ {P2, N2, 0, 0}, /* 1 */ {N2, P2, 0, 0}, /* 2 */ {0, 0, 0, 0} /* backstop */};/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -