xref: /freebsd/contrib/ntp/ntpd/refclock_arbiter.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*
2  * refclock_arbiter - clock driver for Arbiter 1088A/B Satellite
3  *	Controlled Clock
4  */
5 
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9 
10 #if defined(REFCLOCK) && defined(CLOCK_ARBITER)
11 
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <sys/time.h>
15 
16 #include "ntpd.h"
17 #include "ntp_io.h"
18 #include "ntp_refclock.h"
19 #include "ntp_stdlib.h"
20 
21 /*
22  * This driver supports the Arbiter 1088A/B Satellite Controlled Clock.
23  * The claimed accuracy of this clock is 100 ns relative to the PPS
24  * output when receiving four or more satellites.
25  *
26  * The receiver should be configured before starting the NTP daemon, in
27  * order to establish reliable position and operating conditions. It
28  * does not initiate surveying or hold mode. For use with NTP, the
29  * daylight savings time feature should be disables (D0 command) and the
30  * broadcast mode set to operate in UTC (BU command).
31  *
32  * The timecode format supported by this driver is selected by the poll
33  * sequence "B5", which initiates a line in the following format to be
34  * repeated once per second until turned off by the "B0" poll sequence.
35  *
36  * Format B5 (24 ASCII printing characters):
37  *
38  * <cr><lf>i yy ddd hh:mm:ss.000bbb
39  *
40  *	on-time = <cr>
41  *	i = synchronization flag (' ' = locked, '?' = unlocked)
42  *	yy = year of century
43  *	ddd = day of year
44  *	hh:mm:ss = hours, minutes, seconds
45  *	.000 = fraction of second (not used)
46  *	bbb = tailing spaces for fill
47  *
48  * The alarm condition is indicated by a '?' at i, which indicates the
49  * receiver is not synchronized. In normal operation, a line consisting
50  * of the timecode followed by the time quality character (TQ) followed
51  * by the receiver status string (SR) is written to the clockstats file.
52  * The time quality character is encoded in IEEE P1344 standard:
53  *
54  * Format TQ (IEEE P1344 estimated worst-case time quality)
55  *
56  *	0	clock locked, maximum accuracy
57  *	F	clock failure, time not reliable
58  *	4	clock unlocked, accuracy < 1 us
59  *	5	clock unlocked, accuracy < 10 us
60  *	6	clock unlocked, accuracy < 100 us
61  *	7	clock unlocked, accuracy < 1 ms
62  *	8	clock unlocked, accuracy < 10 ms
63  *	9	clock unlocked, accuracy < 100 ms
64  *	A	clock unlocked, accuracy < 1 s
65  *	B	clock unlocked, accuracy < 10 s
66  *
67  * The status string is encoded as follows:
68  *
69  * Format SR (25 ASCII printing characters)
70  *
71  *	V=vv S=ss T=t P=pdop E=ee
72  *
73  *	vv = satellites visible
74  *	ss = relative signal strength
75  *	t = satellites tracked
76  *	pdop = position dilution of precision (meters)
77  *	ee = hardware errors
78  *
79  * If flag4 is set, an additional line consisting of the receiver
80  * latitude (LA), longitude (LO) and elevation (LH) (meters) is written
81  * to this file. If channel B is enabled for deviation mode and connected
82  * to a 1-PPS signal, the last two numbers on the line are the deviation
83  * and standard deviation averaged over the last 15 seconds.
84  */
85 
86 /*
87  * Interface definitions
88  */
89 #define	DEVICE		"/dev/gps%d" /* device name and unit */
90 #define	SPEED232	B9600	/* uart speed (9600 baud) */
91 #define	PRECISION	(-20)	/* precision assumed (about 1 us) */
92 #define	REFID		"GPS " /* reference ID */
93 #define	DESCRIPTION	"Arbiter 1088A/B GPS Receiver" /* WRU */
94 
95 #define	LENARB		24	/* format B5 timecode length */
96 #define MAXSTA		30	/* max length of status string */
97 #define MAXPOS		70	/* max length of position string */
98 
99 /*
100  * ARB unit control structure
101  */
102 struct arbunit {
103 	l_fp	laststamp;	/* last receive timestamp */
104 	int	tcswitch;	/* timecode switch/counter */
105 	char	qualchar;	/* IEEE P1344 quality (TQ command) */
106 	char	status[MAXSTA];	/* receiver status (SR command) */
107 	char	latlon[MAXPOS];	/* receiver position (lat/lon/alt) */
108 };
109 
110 /*
111  * Function prototypes
112  */
113 static	int	arb_start	P((int, struct peer *));
114 static	void	arb_shutdown	P((int, struct peer *));
115 static	void	arb_receive	P((struct recvbuf *));
116 static	void	arb_poll	P((int, struct peer *));
117 
118 /*
119  * Transfer vector
120  */
121 struct	refclock refclock_arbiter = {
122 	arb_start,		/* start up driver */
123 	arb_shutdown,		/* shut down driver */
124 	arb_poll,		/* transmit poll message */
125 	noentry,		/* not used (old arb_control) */
126 	noentry,		/* initialize driver (not used) */
127 	noentry,		/* not used (old arb_buginfo) */
128 	NOFLAGS			/* not used */
129 };
130 
131 
132 /*
133  * arb_start - open the devices and initialize data for processing
134  */
135 static int
136 arb_start(
137 	int unit,
138 	struct peer *peer
139 	)
140 {
141 	register struct arbunit *up;
142 	struct refclockproc *pp;
143 	int fd;
144 	char device[20];
145 
146 	/*
147 	 * Open serial port. Use CLK line discipline, if available.
148 	 */
149 	(void)sprintf(device, DEVICE, unit);
150 	if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
151 		return (0);
152 
153 	/*
154 	 * Allocate and initialize unit structure
155 	 */
156 	if (!(up = (struct arbunit *)emalloc(sizeof(struct arbunit)))) {
157 		(void) close(fd);
158 		return (0);
159 	}
160 	memset((char *)up, 0, sizeof(struct arbunit));
161 	pp = peer->procptr;
162 	pp->io.clock_recv = arb_receive;
163 	pp->io.srcclock = (caddr_t)peer;
164 	pp->io.datalen = 0;
165 	pp->io.fd = fd;
166 	if (!io_addclock(&pp->io)) {
167 		(void) close(fd);
168 		free(up);
169 		return (0);
170 	}
171 	pp->unitptr = (caddr_t)up;
172 
173 	/*
174 	 * Initialize miscellaneous variables
175 	 */
176 	peer->precision = PRECISION;
177 	pp->clockdesc = DESCRIPTION;
178 	memcpy((char *)&pp->refid, REFID, 4);
179 	write(pp->io.fd, "B0", 2);
180 	return (1);
181 }
182 
183 
184 /*
185  * arb_shutdown - shut down the clock
186  */
187 static void
188 arb_shutdown(
189 	int unit,
190 	struct peer *peer
191 	)
192 {
193 	register struct arbunit *up;
194 	struct refclockproc *pp;
195 
196 	pp = peer->procptr;
197 	up = (struct arbunit *)pp->unitptr;
198 	io_closeclock(&pp->io);
199 	free(up);
200 }
201 
202 
203 /*
204  * arb_receive - receive data from the serial interface
205  */
206 static void
207 arb_receive(
208 	struct recvbuf *rbufp
209 	)
210 {
211 	register struct arbunit *up;
212 	struct refclockproc *pp;
213 	struct peer *peer;
214 	l_fp trtmp;
215 	int temp;
216 	u_char	syncchar;	/* synchronization indicator */
217 
218 	/*
219 	 * Initialize pointers and read the timecode and timestamp
220 	 */
221 	peer = (struct peer *)rbufp->recv_srcclock;
222 	pp = peer->procptr;
223 	up = (struct arbunit *)pp->unitptr;
224 	temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
225 
226 	/*
227 	 * Note we get a buffer and timestamp for both a <cr> and <lf>,
228 	 * but only the <cr> timestamp is retained. The program first
229 	 * sends a TQ and expects the echo followed by the time quality
230 	 * character. It then sends a B5 starting the timecode broadcast
231 	 * and expects the echo followed some time later by the on-time
232 	 * character <cr> and then the <lf> beginning the timecode
233 	 * itself. Finally, at the <cr> beginning the next timecode at
234 	 * the next second, the program sends a B0 shutting down the
235 	 * timecode broadcast.
236 	 *
237 	 * If flag4 is set, the program snatches the latitude, longitude
238 	 * and elevation and writes it to the clockstats file.
239 	 */
240 	if (temp == 0)
241 		return;
242 	pp->lastrec = up->laststamp;
243 	up->laststamp = trtmp;
244 	if (temp < 3)
245 		return;
246 	if (up->tcswitch == 0) {
247 
248 		/*
249 		 * Collect statistics. If nothing is recogized, just
250 		 * ignore; sometimes the clock doesn't stop spewing
251 		 * timecodes for awhile after the B0 commant.
252 		 */
253 		if (!strncmp(pp->a_lastcode, "TQ", 2)) {
254 			up->qualchar = pp->a_lastcode[2];
255 			write(pp->io.fd, "SR", 2);
256 		} else if (!strncmp(pp->a_lastcode, "SR", 2)) {
257 			strcpy(up->status, pp->a_lastcode + 2);
258 			if (pp->sloppyclockflag & CLK_FLAG4)
259 				write(pp->io.fd, "LA", 2);
260 			else {
261 				write(pp->io.fd, "B5", 2);
262 				up->tcswitch++;
263 			}
264 		} else if (!strncmp(pp->a_lastcode, "LA", 2)) {
265 			strcpy(up->latlon, pp->a_lastcode + 2);
266 			write(pp->io.fd, "LO", 2);
267 		} else if (!strncmp(pp->a_lastcode, "LO", 2)) {
268 			strcat(up->latlon, " ");
269 			strcat(up->latlon, pp->a_lastcode + 2);
270 			write(pp->io.fd, "LH", 2);
271 		} else if (!strncmp(pp->a_lastcode, "LH", 2)) {
272 			strcat(up->latlon, " ");
273 			strcat(up->latlon, pp->a_lastcode + 2);
274 			write(pp->io.fd, "DB", 2);
275 		} else if (!strncmp(pp->a_lastcode, "DB", 2)) {
276 			strcat(up->latlon, " ");
277 			strcat(up->latlon, pp->a_lastcode + 2);
278 			record_clock_stats(&peer->srcadr, up->latlon);
279 			write(pp->io.fd, "B5", 2);
280 			up->tcswitch++;
281 		}
282 		return;
283 	}
284 	pp->lencode = temp;
285 
286 	/*
287 	 * We get down to business, check the timecode format and decode
288 	 * its contents. If the timecode has valid length, but not in
289 	 * proper format, we declare bad format and exit. If the
290 	 * timecode has invalid length, which sometimes occurs when the
291 	 * B0 amputates the broadcast, we just quietly steal away. Note
292 	 * that the time quality character and receiver status string is
293 	 * tacked on the end for clockstats display.
294 	 */
295 	if (pp->lencode == LENARB) {
296 		/*
297 		 * Timecode format B5: "i yy ddd hh:mm:ss.000   "
298 		 */
299 		pp->a_lastcode[LENARB - 2] = up->qualchar;
300 		strcat(pp->a_lastcode, up->status);
301 		syncchar = ' ';
302 		if (sscanf(pp->a_lastcode, "%c%2d %3d %2d:%2d:%2d",
303 		    &syncchar, &pp->year, &pp->day, &pp->hour,
304 		    &pp->minute, &pp->second) != 6) {
305 			refclock_report(peer, CEVNT_BADREPLY);
306 			write(pp->io.fd, "B0", 2);
307 			return;
308 		}
309 	} else  {
310 		write(pp->io.fd, "B0", 2);
311 		return;
312 	}
313 	up->tcswitch++;
314 
315 	/*
316 	 * We decode the clock dispersion from the time quality
317 	 * character.
318 	 */
319 	switch (up->qualchar) {
320 
321 	    case '0':		/* locked, max accuracy */
322 		pp->disp = 1e-7;
323 		break;
324 
325 	    case '4':		/* unlock accuracy < 1 us */
326 		pp->disp = 1e-6;
327 		break;
328 
329 	    case '5':		/* unlock accuracy < 10 us */
330 		pp->disp = 1e-5;
331 		break;
332 
333 	    case '6':		/* unlock accuracy < 100 us */
334 		pp->disp = 1e-4;
335 		break;
336 
337 	    case '7':		/* unlock accuracy < 1 ms */
338 		pp->disp = .001;
339 		break;
340 
341 	    case '8':		/* unlock accuracy < 10 ms */
342 		pp->disp = .01;
343 		break;
344 
345 	    case '9':		/* unlock accuracy < 100 ms */
346 		pp->disp = .1;
347 		break;
348 
349 	    case 'A':		/* unlock accuracy < 1 s */
350 		pp->disp = 1;
351 		break;
352 
353 	    case 'B':		/* unlock accuracy < 10 s */
354 		pp->disp = 10;
355 		break;
356 
357 	    case 'F':		/* clock failure */
358 		pp->disp = MAXDISPERSE;
359 		refclock_report(peer, CEVNT_FAULT);
360 		write(pp->io.fd, "B0", 2);
361 		return;
362 
363 	    default:
364 		pp->disp = MAXDISPERSE;
365 		refclock_report(peer, CEVNT_BADREPLY);
366 		write(pp->io.fd, "B0", 2);
367 		return;
368 	}
369 	if (syncchar != ' ')
370 		pp->leap = LEAP_NOTINSYNC;
371 	else
372 		pp->leap = LEAP_NOWARNING;
373 #ifdef DEBUG
374 	if (debug)
375 		printf("arbiter: timecode %d %s\n", pp->lencode,
376 		    pp->a_lastcode);
377 #endif
378 	if (up->tcswitch >= NSTAGE)
379 		write(pp->io.fd, "B0", 2);
380 
381 	/*
382 	 * Process the new sample in the median filter and determine the
383 	 * timecode timestamp.
384 	 */
385 	if (!refclock_process(pp))
386 		refclock_report(peer, CEVNT_BADTIME);
387 }
388 
389 
390 /*
391  * arb_poll - called by the transmit procedure
392  */
393 static void
394 arb_poll(
395 	int unit,
396 	struct peer *peer
397 	)
398 {
399 	register struct arbunit *up;
400 	struct refclockproc *pp;
401 
402 	/*
403 	 * Time to poll the clock. The Arbiter clock responds to a "B5"
404 	 * by returning a timecode in the format specified above.
405 	 * Transmission occurs once per second, unless turned off by a
406 	 * "B0". Note there is no checking on state, since this may not
407 	 * be the only customer reading the clock. Only one customer
408 	 * need poll the clock; all others just listen in. If nothing is
409 	 * heard from the clock for two polls, declare a timeout and
410 	 * keep going.
411 	 */
412 	pp = peer->procptr;
413 	up = (struct arbunit *)pp->unitptr;
414 	up->tcswitch = 0;
415 	if (write(pp->io.fd, "TQ", 2) != 2) {
416 		refclock_report(peer, CEVNT_FAULT);
417 	} else
418 		pp->polls++;
419 	if (pp->coderecv == pp->codeproc) {
420 		refclock_report(peer, CEVNT_TIMEOUT);
421 		return;
422 	}
423 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
424 	refclock_receive(peer);
425 }
426 
427 #else
428 int refclock_arbiter_bs;
429 #endif /* REFCLOCK */
430