summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/refclock_chu.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd/refclock_chu.c')
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c215
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
OpenPOWER on IntegriCloud