📄 refclock_chu.c
字号:
/* * refclock_chu - clock driver for Canadian CHU time/frequency station */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_CHU)#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_calendar.h"#include "ntp_stdlib.h"#include <stdio.h>#include <ctype.h>#include <math.h>#ifdef HAVE_AUDIO#include "audio.h"#endif /* HAVE_AUDIO */#define ICOM 1 /* undefine to suppress ICOM code */#ifdef ICOM#include "icom.h"#endif /* ICOM *//* * Audio CHU demodulator/decoder * * This driver synchronizes the computer time using data encoded in * radio transmissions from Canadian time/frequency station CHU in * Ottawa, Ontario. Transmissions are made continuously on 3330 kHz, * 7335 kHz and 14670 kHz in upper sideband, compatible 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 suported workstation hardware and * operating system. These include Solaris, SunOS, FreeBSD, NetBSD and * Linux. In this implementation, only one audio driver and codec can be * supported on a single machine. * * The driver can be compiled to use a Bell 103 compatible modem or * modem chip to receive the radio signal and demodulate the data. * Alternatively, the driver can be compiled to use the audio codec of * the Sun workstation or another with compatible audio drivers. In the * latter case, the driver implements the modem using DSP routines, so * the radio can be connected directly to either the microphone on line * input port. In either case, the driver decodes the data using a * maximum likelihood technique which exploits the considerable degree * of redundancy available to maximize accuracy and minimize errors. * * The CHU time broadcast includes an audio signal compatible with the * Bell 103 modem standard (mark = 2225 Hz, space = 2025 Hz). It consist * of nine, ten-character bursts transmitted at 300 bps and beginning * each second from second 31 to second 39 of the minute. Each character * consists of eight data bits plus one start bit and two stop bits to * encode two hex digits. The burst data consist of five characters (ten * hex digits) followed by a repeat of these characters. In format A, * the characters are repeated in the same polarity; in format B, the * characters are repeated in the opposite polarity. * * Format A bursts are sent at seconds 32 through 39 of the minute in * hex digits * * 6dddhhmmss6dddhhmmss * * The first ten digits encode a frame marker (6) followed by the day * (ddd), hour (hh in UTC), minute (mm) and the second (ss). Since * format A bursts are sent during the third decade of seconds the tens * digit of ss is always 3. The driver uses this to determine correct * burst synchronization. These digits are then repeated with the same * polarity. * * Format B bursts are sent at second 31 of the minute in hex digits * * xdyyyyttaaxdyyyyttaa * * The first ten digits encode a code (x described below) followed by * the DUT1 (d in deciseconds), Gregorian year (yyyy), difference TAI - * UTC (tt) and daylight time indicator (aa) peculiar to Canada. These * digits are then repeated with inverted polarity. * * The x is coded * * 1 Sign of DUT (0 = +) * 2 Leap second warning. One second will be added. * 4 Leap second warning. One second will be subtracted. * 8 Even parity bit for this nibble. * * By design, the last stop bit of the last character in the burst * coincides with 0.5 second. Since characters have 11 bits and are * transmitted at 300 bps, the last stop bit of the first character * coincides with 0.5 - 10 * 11/300 = 0.133 second. Depending on the * UART, character interrupts can vary somewhere between the beginning * of bit 9 and end of bit 11. These eccentricities can be corrected * along with the radio propagation delay using fudge time 1. * * Debugging aids * * The timecode format used for debugging and data recording includes * data helpful in diagnosing problems with the radio signal and serial * connections. With debugging enabled (-d on the ntpd command line), * the driver produces one line for each burst in two formats * corresponding to format A and B. Following is format A: * * n b f s m code * * where n is the number of characters in the burst (0-11), b the burst * distance (0-40), f the field alignment (-1, 0, 1), s the * synchronization distance (0-16), m the burst number (2-9) and code * the burst characters as received. Note that the hex digits in each * character are reversed, so the burst * * 10 38 0 16 9 06851292930685129293 * * is interpreted as containing 11 characters with burst distance 38, * field alignment 0, synchronization distance 16 and burst number 9. * The nibble-swapped timecode shows day 58, hour 21, minute 29 and * second 39. * * When the audio driver is compiled, format A is preceded by * the current gain (0-255) and relative signal level (0-9999). The * receiver folume control should be set so that the gain is somewhere * near the middle of the range 0-255, which results in a signal level * near 1000. * * Following is format B: * * n b s code * * where n is the number of characters in the burst (0-11), b the burst * distance (0-40), s the synchronization distance (0-40) and code the * burst characters as received. Note that the hex digits in each * character are reversed and the last ten digits inverted, so the burst * * 11 40 1091891300ef6e76ecff * * is interpreted as containing 11 characters with burst distance 40. * The nibble-swapped timecode shows DUT1 +0.1 second, year 1998 and TAI * - UTC 31 seconds. * * In addition to the above, the reference timecode is updated and * written to the clockstats file and debug score after the last burst * received in the minute. The format is * * qq yyyy ddd hh:mm:ss nn dd tt * * where qq are the error flags, as described below, yyyy is the year, * ddd the day, hh:mm:ss the time of day, nn the number of format A * bursts received during the previous minute, dd the decoding distance * and tt the number of timestamps. The error flags are cleared after * every update. * * Fudge factors * * For accuracies better than the low millisceconds, fudge time1 can be * set to the radio propagation delay from CHU to the receiver. This can * be done conviently using the minimuf program. * * Fudge flag4 causes the dubugging output described above to be * recorded in the clockstats file. When the audio driver is compiled, * 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. * * The audio codec code is normally compiled in the driver if the * architecture supports it (HAVE_AUDIO defined), but is used only if * the link /dev/chu_audio is defined and valid. The serial port code is * always compiled in the driver, but is used only if the autdio codec * is not available and the link /dev/chu%d is defined and valid. * * The ICOM code is normally compiled in the driver if selected (ICOM * defined), but is used only if the link /dev/icom%d is defined and * valid and the mode keyword on the server configuration command * specifies a nonzero mode (ICOM ID select code). The C-IV speed is * 9600 bps if the high order 0x80 bit of the mode is zero and 1200 bps * if one. The C-IV trace is turned on if the debug level is greater * than one. *//* * Interface definitions */#define SPEED232 B300 /* uart speed (300 baud) */#define PRECISION (-10) /* precision assumed (about 1 ms) */#define REFID "CHU" /* reference ID */#define DEVICE "/dev/chu%d" /* device name and unit */#define SPEED232 B300 /* UART speed (300 baud) */#ifdef ICOM#define TUNE .001 /* offset for narrow filter (kHz) */#define DWELL 5 /* minutes in a probe cycle */#define NCHAN 3 /* number of channels */#define ISTAGE 3 /* number of integrator stages */#endif /* ICOM */#ifdef HAVE_AUDIO/* * Audio demodulator definitions */#define SECOND 8000 /* nominal sample rate (Hz) */#define BAUD 300 /* modulation rate (bps) */#define OFFSET 128 /* companded sample offset */#define SIZE 256 /* decompanding table size */#define MAXSIG 6000. /* maximum signal level */#define MAXCLP 100 /* max clips above reference per s */#define LIMIT 1000. /* soft limiter threshold */#define AGAIN 6. /* baseband gain */#define LAG 10 /* discriminator lag */#define DEVICE_AUDIO "/dev/audio" /* device name */#define DESCRIPTION "CHU Audio/Modem Receiver" /* WRU */#define AUDIO_BUFSIZ 240 /* audio buffer size (30 ms) */#else#define DESCRIPTION "CHU Modem Receiver" /* WRU */#endif /* HAVE_AUDIO *//* * Decoder definitions */#define CHAR (11. / 300.) /* character time (s) */#define FUDGE .185 /* offset to first stop bit (s) */#define BURST 11 /* max characters per burst */#define MINCHAR 9 /* min characters per burst */#define MINDIST 28 /* min burst distance (of 40) */#define MINBURST 4 /* min bursts in minute */#define MINSYNC 8 /* min sync distance (of 16) */#define MINSTAMP 20 /* min timestamps (of 60) */#define METRIC 50. /* min channel metric */#define PANIC 1440 /* panic timeout (m) */#define HOLD 30 /* reach hold (m) *//* * Hex extension codes (>= 16) */#define HEX_MISS 16 /* miss _ */#define HEX_SOFT 17 /* soft error * */#define HEX_HARD 18 /* hard error = *//* * Status bits (status) */#define RUNT 0x0001 /* runt burst */#define NOISE 0x0002 /* noise burst */#define BFRAME 0x0004 /* invalid format B frame sync */#define BFORMAT 0x0008 /* invalid format B data */#define AFRAME 0x0010 /* invalid format A frame sync */#define AFORMAT 0x0020 /* invalid format A data */#define DECODE 0x0040 /* invalid data decode */#define STAMP 0x0080 /* too few timestamps */#define AVALID 0x0100 /* valid A frame */#define BVALID 0x0200 /* valid B frame */#define INSYNC 0x0400 /* clock synchronized *//* * Alarm status bits (alarm) * * These alarms are set at the end of a minute in which at least one * burst was received. SYNERR is raised if the AFRAME or BFRAME status * bits are set during the minute, FMTERR is raised if the AFORMAT or * BFORMAT status bits are set, DECERR is raised if the DECODE status * bit is set and TSPERR is raised if the STAMP status bit is set. */#define SYNERR 0x01 /* frame sync error */#define FMTERR 0x02 /* data format error */#define DECERR 0x04 /* data decoding error */#define TSPERR 0x08 /* insufficient data */#ifdef HAVE_AUDIO/* * Maximum likelihood UART structure. There are eight of these * corresponding to the number of phases. */ struct surv { double shift[12]; /* mark register */ double es_max, es_min; /* max/min envelope signals */ double dist; /* sample distance */ int uart; /* decoded character */};#endif /* HAVE_AUDIO */#ifdef ICOM/* * CHU station structure. There are three of these corresponding to the * three frequencies. */struct xmtr { double integ[ISTAGE]; /* circular integrator */ double metric; /* integrator sum */ int iptr; /* integrator pointer */ int probe; /* dwells since last probe */};#endif /* ICOM *//* * CHU unit control structure */struct chuunit { u_char decode[20][16]; /* maximum likelihood decoding matrix */ l_fp cstamp[BURST]; /* character timestamps */ l_fp tstamp[MAXSTAGE]; /* timestamp samples */ l_fp timestamp; /* current buffer timestamp */ l_fp laststamp; /* last buffer timestamp */ l_fp charstamp; /* character time as a l_fp */ int errflg; /* error flags */ int status; /* status bits */ char ident[5]; /* station ID and channel */#ifdef ICOM int fd_icom; /* ICOM file descriptor */ int chan; /* data channel */ int achan; /* active channel */ int dwell; /* dwell cycle */ struct xmtr xmtr[NCHAN]; /* station metric */#endif /* ICOM */ /* * Character burst variables */ int cbuf[BURST]; /* character buffer */ int ntstamp; /* number of timestamp samples */ int ndx; /* buffer start index */ int prevsec; /* previous burst second */ int burdist; /* burst distance */ int syndist; /* sync distance */ int burstcnt; /* format A bursts this minute */ /* * Format particulars */ int leap; /* leap/dut code */ int dut; /* UTC1 correction */ int tai; /* TAI - UTC correction */ int dst; /* Canadian DST code */#ifdef HAVE_AUDIO /* * Audio codec variables */ int fd_audio; /* audio port file descriptor */ double comp[SIZE]; /* decompanding table */ int port; /* codec port */ int gain; /* codec gain */ int mongain; /* codec monitor gain */ int clipcnt; /* sample clip count */ int seccnt; /* second interval counter */ /* * Modem variables */ l_fp tick; /* audio sample increment */ double bpf[9]; /* IIR bandpass filter */ double disc[LAG]; /* discriminator shift register */ double lpf[27]; /* FIR lowpass filter */ double monitor; /* audio monitor */ double maxsignal; /* signal level */ int discptr; /* discriminator pointer */ /* * Maximum likelihood UART variables */ double baud; /* baud interval */ struct surv surv[8]; /* UART survivor structures */ int decptr; /* decode pointer */ int dbrk; /* holdoff counter */#endif /* HAVE_AUDIO */};/* * Function prototypes */static int chu_start P((int, struct peer *));static void chu_shutdown P((int, struct peer *));static void chu_receive P((struct recvbuf *));static void chu_poll P((int, struct peer *));/* * More function prototypes */static void chu_decode P((struct peer *, int));static void chu_burst P((struct peer *));static void chu_clear P((struct peer *));static void chu_a P((struct peer *, int));static void chu_b P((struct peer *, int));static int chu_dist P((int, int));static double chu_major P((struct peer *));#ifdef HAVE_AUDIOstatic void chu_uart P((struct surv *, double));static void chu_rf P((struct peer *, double));static void chu_gain P((struct peer *));static void chu_audio_receive P((struct recvbuf *rbufp));#endif /* HAVE_AUDIO */#ifdef ICOMstatic int chu_newchan P((struct peer *, double));#endif /* ICOM */static void chu_serial_receive P((struct recvbuf *rbufp));/* * Global variables */static char hexchar[] = "0123456789abcdef_*=";#ifdef ICOM/* * Note the tuned frequencies are 1 kHz higher than the carrier. CHU * transmits on USB with carrier so we can use AM and the narrow SSB * filter. */static double qsy[NCHAN] = {3.330, 7.335, 14.670}; /* freq (MHz) */#endif /* ICOM *//* * Transfer vector */struct refclock refclock_chu = { chu_start, /* start up driver */ chu_shutdown, /* shut down driver */ chu_poll, /* transmit poll message */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -