diff options
Diffstat (limited to 'contrib/ntp/ntpd/refclock_as2201.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_as2201.c | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/contrib/ntp/ntpd/refclock_as2201.c b/contrib/ntp/ntpd/refclock_as2201.c deleted file mode 100644 index f04d417b..0000000 --- a/contrib/ntp/ntpd/refclock_as2201.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * refclock_as2201 - clock driver for the Austron 2201A GPS - * Timing Receiver - */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined(REFCLOCK) && defined(CLOCK_AS2201) - -#include "ntpd.h" -#include "ntp_io.h" -#include "ntp_refclock.h" -#include "ntp_unixtime.h" -#include "ntp_stdlib.h" - -#include <stdio.h> -#include <ctype.h> - -/* - * This driver supports the Austron 2200A/2201A GPS Receiver with - * Buffered RS-232-C Interface Module. Note that the original 2200/2201 - * receivers will not work reliably with this driver, since the older - * design cannot accept input commands at any reasonable data rate. - * - * The program sends a "*toc\r" to the radio and expects a response of - * the form "yy:ddd:hh:mm:ss.mmm\r" where yy = year of century, ddd = - * day of year, hh:mm:ss = second of day and mmm = millisecond of - * second. Then, it sends statistics commands to the radio and expects - * a multi-line reply showing the corresponding statistics or other - * selected data. Statistics commands are sent in order as determined by - * a vector of commands; these might have to be changed with different - * radio options. If flag4 of the fudge configuration command is set to - * 1, the statistics data are written to the clockstats file for later - * processing. - * - * In order for this code to work, the radio must be placed in non- - * interactive mode using the "off" command and with a single <cr> - * response using the "term cr" command. The setting of the "echo" - * and "df" commands does not matter. The radio should select UTC - * timescale using the "ts utc" command. - * - * There are two modes of operation for this driver. The first with - * default configuration is used with stock kernels and serial-line - * drivers and works with almost any machine. In this mode the driver - * assumes the radio captures a timestamp upon receipt of the "*" that - * begins the driver query. Accuracies in this mode are in the order of - * a millisecond or two and the receiver can be connected to only one - * host. - * - * The second mode of operation can be used for SunOS kernels that have - * been modified with the ppsclock streams module included in this - * distribution. The mode is enabled if flag3 of the fudge configuration - * command has been set to 1. In this mode a precise timestamp is - * available using a gadget box and 1-pps signal from the receiver. This - * improves the accuracy to the order of a few tens of microseconds. In - * addition, the serial output and 1-pps signal can be bussed to more - * than one hosts, but only one of them should be connected to the - * radio input data line. - */ - -/* - * GPS Definitions - */ -#define SMAX 200 /* statistics buffer length */ -#define DEVICE "/dev/gps%d" /* device name and unit */ -#define SPEED232 B9600 /* uart speed (9600 baud) */ -#define PRECISION (-20) /* precision assumed (about 1 us) */ -#define REFID "GPS\0" /* reference ID */ -#define DESCRIPTION "Austron 2201A GPS Receiver" /* WRU */ - -#define LENTOC 19 /* yy:ddd:hh:mm:ss.mmm timecode lngth */ - -/* - * AS2201 unit control structure. - */ -struct as2201unit { - char *lastptr; /* statistics buffer pointer */ - char stats[SMAX]; /* statistics buffer */ - int linect; /* count of lines remaining */ - int index; /* current statistics command */ -}; - -/* - * Radio commands to extract statitistics - * - * A command consists of an ASCII string terminated by a <cr> (\r). The - * command list consist of a sequence of commands terminated by a null - * string ("\0"). One command from the list is sent immediately - * following each received timecode (*toc\r command) and the ASCII - * strings received from the radio are saved along with the timecode in - * the clockstats file. Subsequent commands are sent at each timecode, - * with the last one in the list followed by the first one. The data - * received from the radio consist of ASCII strings, each terminated by - * a <cr> (\r) character. The number of strings for each command is - * specified as the first line of output as an ASCII-encode number. Note - * that the ETF command requires the Input Buffer Module and the LORAN - * commands require the LORAN Assist Module. However, if these modules - * are not installed, the radio and this driver will continue to operate - * successfuly, but no data will be captured for these commands. - */ -static char stat_command[][30] = { - "ITF\r", /* internal time/frequency */ - "ETF\r", /* external time/frequency */ - "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */ - "LORAN TDATA\r", /* LORAN signal data */ - "ID;OPT;VER\r", /* model; options; software version */ - - "ITF\r", /* internal time/frequency */ - "ETF\r", /* external time/frequency */ - "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */ - "TRSTAT\r", /* satellite tracking status */ - "POS;PPS;PPSOFF\r", /* position, pps source, offsets */ - - "ITF\r", /* internal time/frequency */ - "ETF\r", /* external time/frequency */ - "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */ - "LORAN TDATA\r", /* LORAN signal data */ - "UTC\r", /* UTC leap info */ - - "ITF\r", /* internal time/frequency */ - "ETF\r", /* external time/frequency */ - "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */ - "TRSTAT\r", /* satellite tracking status */ - "OSC;ET;TEMP\r", /* osc type; tune volts; oven temp */ - "\0" /* end of table */ -}; - -/* - * Function prototypes - */ -static int as2201_start P((int, struct peer *)); -static void as2201_shutdown P((int, struct peer *)); -static void as2201_receive P((struct recvbuf *)); -static void as2201_poll P((int, struct peer *)); - -/* - * Transfer vector - */ -struct refclock refclock_as2201 = { - as2201_start, /* start up driver */ - as2201_shutdown, /* shut down driver */ - as2201_poll, /* transmit poll message */ - noentry, /* not used (old as2201_control) */ - noentry, /* initialize driver (not used) */ - noentry, /* not used (old as2201_buginfo) */ - NOFLAGS /* not used */ -}; - - -/* - * as2201_start - open the devices and initialize data for processing - */ -static int -as2201_start( - int unit, - struct peer *peer - ) -{ - register struct as2201unit *up; - struct refclockproc *pp; - int fd; - char gpsdev[20]; - - /* - * Open serial port. Use CLK line discipline, if available. - */ - (void)sprintf(gpsdev, DEVICE, unit); - if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_CLK))) - return (0); - - /* - * Allocate and initialize unit structure - */ - if (!(up = (struct as2201unit *) - emalloc(sizeof(struct as2201unit)))) { - (void) close(fd); - return (0); - } - memset((char *)up, 0, sizeof(struct as2201unit)); - pp = peer->procptr; - pp->io.clock_recv = as2201_receive; - pp->io.srcclock = (caddr_t)peer; - pp->io.datalen = 0; - pp->io.fd = fd; - if (!io_addclock(&pp->io)) { - (void) close(fd); - free(up); - return (0); - } - pp->unitptr = (caddr_t)up; - - /* - * Initialize miscellaneous variables - */ - peer->precision = PRECISION; - peer->burst = NSTAGE; - pp->clockdesc = DESCRIPTION; - memcpy((char *)&pp->refid, REFID, 4); - up->lastptr = up->stats; - up->index = 0; - return (1); -} - - -/* - * as2201_shutdown - shut down the clock - */ -static void -as2201_shutdown( - int unit, - struct peer *peer - ) -{ - register struct as2201unit *up; - struct refclockproc *pp; - - pp = peer->procptr; - up = (struct as2201unit *)pp->unitptr; - io_closeclock(&pp->io); - free(up); -} - - -/* - * as2201__receive - receive data from the serial interface - */ -static void -as2201_receive( - struct recvbuf *rbufp - ) -{ - register struct as2201unit *up; - struct refclockproc *pp; - struct peer *peer; - l_fp trtmp; - - /* - * Initialize pointers and read the timecode and timestamp. - */ - peer = (struct peer *)rbufp->recv_srcclock; - pp = peer->procptr; - up = (struct as2201unit *)pp->unitptr; - pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp); -#ifdef DEBUG - if (debug) - printf("gps: timecode %d %d %s\n", - up->linect, pp->lencode, pp->a_lastcode); -#endif - if (pp->lencode == 0) - return; - - /* - * If linect is greater than zero, we must be in the middle of a - * statistics operation, so simply tack the received data at the - * end of the statistics string. If not, we could either have - * just received the timecode itself or a decimal number - * indicating the number of following lines of the statistics - * reply. In the former case, write the accumulated statistics - * data to the clockstats file and continue onward to process - * the timecode; in the later case, save the number of lines and - * quietly return. - */ - if (pp->sloppyclockflag & CLK_FLAG2) - pp->lastrec = trtmp; - if (up->linect > 0) { - up->linect--; - if ((int)(up->lastptr - up->stats + pp->lencode) > SMAX - 2) - return; - *up->lastptr++ = ' '; - (void)strcpy(up->lastptr, pp->a_lastcode); - up->lastptr += pp->lencode; - return; - } else { - if (pp->lencode == 1) { - up->linect = atoi(pp->a_lastcode); - return; - } else { - record_clock_stats(&peer->srcadr, up->stats); -#ifdef DEBUG - if (debug) - printf("gps: stat %s\n", up->stats); -#endif - } - } - up->lastptr = up->stats; - *up->lastptr = '\0'; - - /* - * We get down to business, check the timecode format and decode - * its contents. If the timecode has invalid length or is not in - * proper format, we declare bad format and exit. - */ - if (pp->lencode < LENTOC) { - refclock_report(peer, CEVNT_BADREPLY); - return; - } - - /* - * Timecode format: "yy:ddd:hh:mm:ss.mmm" - */ - if (sscanf(pp->a_lastcode, "%2d:%3d:%2d:%2d:%2d.%3ld", &pp->year, - &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->nsec) - != 6) { - refclock_report(peer, CEVNT_BADREPLY); - return; - } - pp->nsec *= 1000000; - - /* - * Test for synchronization (this is a temporary crock). - */ - if (pp->a_lastcode[2] != ':') - pp->leap = LEAP_NOTINSYNC; - else - pp->leap = LEAP_NOWARNING; - - /* - * Process the new sample in the median filter and determine the - * timecode timestamp. - */ - if (!refclock_process(pp)) { - refclock_report(peer, CEVNT_BADTIME); - return; - } - - /* - * If CLK_FLAG4 is set, initialize the statistics buffer and - * send the next command. If not, simply write the timecode to - * the clockstats file. - */ - (void)strcpy(up->lastptr, pp->a_lastcode); - up->lastptr += pp->lencode; - if (pp->sloppyclockflag & CLK_FLAG4) { - *up->lastptr++ = ' '; - (void)strcpy(up->lastptr, stat_command[up->index]); - up->lastptr += strlen(stat_command[up->index]); - up->lastptr--; - *up->lastptr = '\0'; - (void)write(pp->io.fd, stat_command[up->index], - strlen(stat_command[up->index])); - up->index++; - if (*stat_command[up->index] == '\0') - up->index = 0; - } -} - - -/* - * as2201_poll - called by the transmit procedure - * - * We go to great pains to avoid changing state here, since there may be - * more than one eavesdropper receiving the same timecode. - */ -static void -as2201_poll( - int unit, - struct peer *peer - ) -{ - struct refclockproc *pp; - - /* - * Send a "\r*toc\r" to get things going. We go to great pains - * to avoid changing state, since there may be more than one - * eavesdropper watching the radio. - */ - pp = peer->procptr; - if (write(pp->io.fd, "\r*toc\r", 6) != 6) { - refclock_report(peer, CEVNT_FAULT); - } else { - pp->polls++; - if (!(pp->sloppyclockflag & CLK_FLAG2)) - get_systime(&pp->lastrec); - } - if (peer->burst > 0) - return; - if (pp->coderecv == pp->codeproc) { - refclock_report(peer, CEVNT_TIMEOUT); - return; - } - refclock_receive(peer); - peer->burst = NSTAGE; -} - -#else -int refclock_as2201_bs; -#endif /* REFCLOCK */ |