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