diff options
Diffstat (limited to 'contrib/ntp/ntpd/refclock_chu.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_chu.c | 215 |
1 files changed, 143 insertions, 72 deletions
diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c index 4235b8e..10fcea5 100644 --- a/contrib/ntp/ntpd/refclock_chu.c +++ b/contrib/ntp/ntpd/refclock_chu.c @@ -7,20 +7,19 @@ #if defined(REFCLOCK) && defined(CLOCK_CHU) -#include <stdio.h> -#include <ctype.h> -#include <sys/time.h> -#include <time.h> -#include <math.h> - #include "ntpd.h" #include "ntp_io.h" #include "ntp_refclock.h" #include "ntp_calendar.h" #include "ntp_stdlib.h" -#ifdef AUDIO_CHU + +#include <stdio.h> +#include <ctype.h> +#include <math.h> + +#ifdef HAVE_AUDIO #include "audio.h" -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ #define ICOM 1 /* undefine to suppress ICOM code */ @@ -173,10 +172,18 @@ * Fudge flag3 enables audio monitoring of the input signal. For this * purpose, the speaker volume must be set before the driver is started. * - * 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. + * 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 alwasy 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 @@ -184,12 +191,13 @@ #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 DWELL 5 /* minutes before qsy */ #define NCHAN 3 /* number of channels */ #endif /* ICOM */ -#ifdef AUDIO_CHU -#define DESCRIPTION "CHU Modem Receiver" /* WRU */ +#ifdef HAVE_AUDIO /* * Audio demodulator definitions @@ -202,11 +210,11 @@ #define LIMIT 1000. /* soft limiter threshold */ #define AGAIN 6. /* baseband gain */ #define LAG 10 /* discriminator lag */ +#define DEVICE_AUDIO "/dev/chu_audio" /* device name */ +#define DESCRIPTION "CHU Audio/Modem Receiver" /* WRU */ #else -#define DEVICE "/dev/chu%d" /* device name and unit */ -#define SPEED232 B300 /* UART speed (300 baud) */ -#define DESCRIPTION "CHU Audio Receiver" /* WRU */ -#endif /* AUDIO_CHU */ +#define DESCRIPTION "CHU Modem Receiver" /* WRU */ +#endif /* HAVE_AUDIO */ /* * Decoder definitions @@ -255,14 +263,14 @@ #define DECERR 0x04 /* data decoding error */ #define TSPERR 0x08 /* insufficient data */ -#ifdef AUDIO_CHU +#ifdef HAVE_AUDIO 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 /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ /* * CHU unit control structure @@ -279,9 +287,9 @@ struct chuunit { int bufptr; /* buffer index pointer */ char ident[10]; /* transmitter frequency */ #ifdef ICOM + int fd_icom; /* ICOM file descriptor */ int chan; /* frequency identifier */ int dwell; /* dwell minutes at current frequency */ - int fd_icom; /* ICOM file descriptor */ #endif /* ICOM */ /* @@ -304,10 +312,11 @@ struct chuunit { int tai; /* TAI - UTC correction */ int dst; /* Canadian DST code */ -#ifdef AUDIO_CHU +#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 */ @@ -333,7 +342,7 @@ struct chuunit { struct surv surv[8]; /* UART survivor structures */ int decptr; /* decode pointer */ int dbrk; /* holdoff counter */ -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ }; /* @@ -354,11 +363,13 @@ static void chu_a P((struct peer *, int)); static void chu_b P((struct peer *, int)); static int chu_dist P((int, int)); static int chu_major P((struct peer *)); -#ifdef AUDIO_CHU +#ifdef HAVE_AUDIO static void chu_uart P((struct surv *, double)); static void chu_rf P((struct peer *, double)); static void chu_gain P((struct peer *)); -#endif /* AUDIO_CHU */ +static void chu_audio_receive P((struct recvbuf *rbufp)); +#endif /* HAVE_AUDIO */ +static void chu_serial_receive P((struct recvbuf *rbufp)); /* * Global variables @@ -393,43 +404,52 @@ chu_start( { struct chuunit *up; struct refclockproc *pp; + char device[20]; /* device name */ int fd; /* file descriptor */ #ifdef ICOM char tbuf[80]; /* trace buffer */ int temp; #endif /* ICOM */ -#ifdef AUDIO_CHU +#ifdef HAVE_AUDIO + int fd_audio; /* audio port file descriptor */ int i; /* index */ double step; /* codec adjustment */ /* - * Open audio device + * Open audio device. */ - fd = audio_init(); - if (fd < 0) - return (0); + fd_audio = audio_init(DEVICE_AUDIO); #ifdef DEBUG - if (debug) + if (fd_audio > 0 && debug) audio_show(); #endif -#else - char device[20]; /* device name */ /* * Open serial port in raw mode. */ - (void)sprintf(device, DEVICE, unit); - if (!(fd = refclock_open(device, SPEED232, LDISC_RAW))) { - return (0); + if (fd_audio > 0) { + fd = fd_audio; + } else { + sprintf(device, DEVICE, unit); + fd = refclock_open(device, SPEED232, LDISC_RAW); } -#endif /* AUDIO_CHU */ +#else /* HAVE_AUDIO */ + + /* + * Open serial port in raw mode. + */ + sprintf(device, DEVICE, unit); + fd = refclock_open(device, SPEED232, LDISC_RAW); +#endif /* HAVE_AUDIO */ + if (fd <= 0) + return (0); /* * Allocate and initialize unit structure */ if (!(up = (struct chuunit *) emalloc(sizeof(struct chuunit)))) { - (void) close(fd); + close(fd); return (0); } memset((char *)up, 0, sizeof(struct chuunit)); @@ -440,7 +460,7 @@ chu_start( pp->io.datalen = 0; pp->io.fd = fd; if (!io_addclock(&pp->io)) { - (void)close(fd); + close(fd); free(up); return (0); } @@ -452,13 +472,15 @@ chu_start( pp->clockdesc = DESCRIPTION; memcpy((char *)&pp->refid, REFID, 4); DTOLFP(CHAR, &up->charstamp); -#ifdef AUDIO_CHU - up->gain = 127; +#ifdef HAVE_AUDIO /* * The companded samples are encoded sign-magnitude. The table - * contains all the 256 values in the interest of speed. + * contains all the 256 values in the interest of speed. We do + * this even if the audio codec is not available. C'est la lazy. */ + up->fd_audio = fd_audio; + up->gain = 127; up->comp[0] = up->comp[OFFSET] = 0.; up->comp[1] = 1; up->comp[OFFSET + 1] = -1.; up->comp[2] = 3; up->comp[OFFSET + 2] = -3.; @@ -470,7 +492,7 @@ chu_start( step *= 2.; } DTOLFP(1. / SECOND, &up->tick); -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ strcpy(up->ident, "X"); #ifdef ICOM temp = 0; @@ -478,8 +500,8 @@ chu_start( if (debug > 1) temp = P_TRACE; #endif - if (peer->ttl > 0) { - if (peer->ttl & 0x80) + if (peer->ttlmax > 0) { + if (peer->ttlmax & 0x80) up->fd_icom = icom_init("/dev/icom", B1200, temp); else @@ -487,7 +509,7 @@ chu_start( temp); } if (up->fd_icom > 0) { - if (icom_freq(up->fd_icom, peer->ttl & 0x7f, + if (icom_freq(up->fd_icom, peer->ttlmax & 0x7f, qsy[up->chan]) < 0) { NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT) msyslog(LOG_ERR, @@ -524,22 +546,58 @@ chu_shutdown( pp = peer->procptr; up = (struct chuunit *)pp->unitptr; + if (up == NULL) + return; io_closeclock(&pp->io); if (up->fd_icom > 0) close(up->fd_icom); free(up); } -#ifdef AUDIO_CHU - /* - * chu_receive - receive data from the audio device + * chu_receive - receive data from the audio or serial device */ static void chu_receive( struct recvbuf *rbufp /* receive buffer structure pointer */ ) { +#ifdef HAVE_AUDIO + struct chuunit *up; + struct refclockproc *pp; + struct peer *peer; + + peer = (struct peer *)rbufp->recv_srcclock; + pp = peer->procptr; + up = (struct chuunit *)pp->unitptr; + + /* + * If the audio codec is warmed up, the buffer contains codec + * samples which need to be demodulated and decoded into CHU + * characters using the software UART. Otherwise, the buffer + * contains CHU characters from the serial port, so the software + * UART is bypassed. In this case the CPU will probably run a + * few degrees cooler. + */ + if (up->fd_audio > 0) + chu_audio_receive(rbufp); + else + chu_serial_receive(rbufp); +#else + chu_serial_receive(rbufp); +#endif /* HAVE_AUDIO */ +} + +#ifdef HAVE_AUDIO + +/* + * chu_audio_receive - receive data from the audio device + */ +static void +chu_audio_receive( + struct recvbuf *rbufp /* receive buffer structure pointer */ + ) +{ struct chuunit *up; struct refclockproc *pp; struct peer *peer; @@ -712,9 +770,9 @@ chu_rf( up->disc[up->discptr] = limit; up->discptr = (up->discptr + 1 ) % LAG; if (disc >= 0) - disc = sqrt(disc); + disc = SQRT(disc); else - disc = -sqrt(-disc); + disc = -SQRT(-disc); /* * Lowpass filter. Raised cosine, Ts = 1 / 300, beta = 0.1. @@ -849,14 +907,14 @@ chu_uart( sp->es_min = es_min; sp->dist = dist / (11 * (es_max - es_min)); } +#endif /* HAVE_AUDIO */ -#else /* AUDIO_CHU */ /* - * chu_receive - receive data from the serial interface + * chu_serial_receive - receive data from the serial device */ static void -chu_receive( +chu_serial_receive( struct recvbuf *rbufp /* receive buffer structure pointer */ ) { @@ -877,11 +935,10 @@ chu_receive( dpt = (u_char *)&rbufp->recv_space; chu_decode(peer, *dpt); } -#endif /* AUDIO_CHU */ /* - * chu_decode - decode the data + * chu_decode - decode the character data */ static void chu_decode( @@ -1108,14 +1165,20 @@ chu_a( if (temp > 9 || k + 9 >= nchar || temp != ((up->cbuf[k + 9] >> 4) & 0xf)) temp = 0; -#ifdef AUDIO_CHU - sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ", - up->status, up->maxsignal, nchar, up->burdist, k, - up->syndist, temp); +#ifdef HAVE_AUDIO + if (up->fd_audio) + sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ", + up->status, up->maxsignal, nchar, up->burdist, k, + up->syndist, temp); + else + sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", + up->status, nchar, up->burdist, k, up->syndist, + temp); + #else sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", up->status, nchar, up->burdist, k, up->syndist, temp); -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ for (i = 0; i < nchar; i++) sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]); @@ -1221,7 +1284,7 @@ chu_poll( } else if (up->fd_icom > 0) { up->dwell = 0; up->chan = (up->chan + 1) % NCHAN; - icom_freq(up->fd_icom, peer->ttl & 0x7f, qsy[up->chan]); + icom_freq(up->fd_icom, peer->ttlmax & 0x7f, qsy[up->chan]); sprintf(up->ident, "%.3f", qsy[up->chan]); sprintf(tbuf, "chu: QSY to %s MHz", up->ident); record_clock_stats(&peer->srcadr, tbuf); @@ -1255,19 +1318,28 @@ chu_poll( } else { pp->leap = LEAP_NOWARNING; } -#ifdef AUDIO_CHU - sprintf(pp->a_lastcode, - "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d", - synchar, qual, pp->year, pp->day, pp->hour, pp->minute, - pp->second, leapchar, up->dst, up->dut, minset, up->gain, - up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp); +#ifdef HAVE_AUDIO + if (up->fd_audio) + sprintf(pp->a_lastcode, + "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d", + synchar, qual, pp->year, pp->day, pp->hour, + pp->minute, pp->second, leapchar, up->dst, up->dut, + minset, up->gain, up->ident, up->tai, up->burstcnt, + up->mindist, up->ntstamp); + else + sprintf(pp->a_lastcode, + "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d", + synchar, qual, pp->year, pp->day, pp->hour, + pp->minute, pp->second, leapchar, up->dst, up->dut, + minset, up->ident, up->tai, up->burstcnt, + up->mindist, up->ntstamp); #else sprintf(pp->a_lastcode, "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d", synchar, qual, pp->year, pp->day, pp->hour, pp->minute, pp->second, leapchar, up->dst, up->dut, minset, up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp); -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ pp->lencode = strlen(pp->a_lastcode); /* @@ -1390,7 +1462,6 @@ chu_major( return (0); } pp->lastref = offset; - pp->variance = 0; for (i = 0; i < up->ntstamp; i++) { toffset = offset; L_SUB(&toffset, &up->tstamp[i]); @@ -1462,7 +1533,7 @@ chu_dist( } -#ifdef AUDIO_CHU +#ifdef HAVE_AUDIO /* * chu_gain - adjust codec gain * @@ -1500,7 +1571,7 @@ chu_gain( audio_gain(up->gain, up->port); up->clipcnt = 0; } -#endif /* AUDIO_CHU */ +#endif /* HAVE_AUDIO */ #else |