1193326Sed/*
2193326Sed * This software was developed by the Software and Component Technologies
3193326Sed * group of Trimble Navigation, Ltd.
4193326Sed *
5193326Sed * Copyright (c) 1997, 1998, 1999, 2000  Trimble Navigation Ltd.
6193326Sed * All rights reserved.
7193326Sed *
8193326Sed * Redistribution and use in source and binary forms, with or without
9193326Sed * modification, are permitted provided that the following conditions
10193326Sed * are met:
11193326Sed * 1. Redistributions of source code must retain the above copyright
12193326Sed *    notice, this list of conditions and the following disclaimer.
13193326Sed * 2. Redistributions in binary form must reproduce the above copyright
14193326Sed *    notice, this list of conditions and the following disclaimer in the
15193326Sed *    documentation and/or other materials provided with the distribution.
16193326Sed * 3. All advertising materials mentioning features or use of this software
17193326Sed *    must display the following acknowledgement:
18193326Sed *    This product includes software developed by Trimble Navigation, Ltd.
19193326Sed * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
20193326Sed *    promote products derived from this software without specific prior
21193326Sed *    written permission.
22193326Sed *
23193326Sed * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
24193326Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25193326Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26193326Sed * ARE DISCLAIMED.  IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
27226633Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28224145Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29224145Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30224145Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31280031Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32276479Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33224145Sdim * SUCH DAMAGE.
34224145Sdim */
35224145Sdim
36224145Sdim/*
37224145Sdim * refclock_palisade - clock driver for the Trimble Palisade GPS
38224145Sdim * timing receiver
39224145Sdim *
40224145Sdim * For detailed information on this program, please refer to the html
41224145Sdim * Refclock 29 page accompanying the NTP distribution.
42309124Sdim *
43309124Sdim * for questions / bugs / comments, contact:
44309124Sdim * sven_dietrich@trimble.com
45224145Sdim *
46224145Sdim * Sven-Thorsten Dietrich
47224145Sdim * 645 North Mary Avenue
48224145Sdim * Post Office Box 3642
49224145Sdim * Sunnyvale, CA 94088-3642
50224145Sdim *
51224145Sdim * Version 2.45; July 14, 1999
52224145Sdim *
53224145Sdim *
54224145Sdim *
55224145Sdim * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
56224145Sdim *	     Contact: Fernando Pablo Hauscarriaga
57224145Sdim * 	     E-mail: fernandoph@iar.unlp.edu.ar
58224145Sdim * 	     Home page: www.iar.unlp.edu.ar/~fernandoph
59224145Sdim *		  Instituto Argentino de Radioastronomia
60224145Sdim *			    www.iar.unlp.edu.ar
61224145Sdim *
62224145Sdim * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
63224145Sdim *	     now we use mode 2 for decode thunderbolt packets.
64224145Sdim *	     Fernando P. Hauscarriaga
65224145Sdim *
66224145Sdim * 30/08/09: Added support for Trimble Acutime Gold Receiver.
67224145Sdim *	     Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
68224145Sdim *
69234353Sdim * 21/04/18: Added support for Resolution devices.
70234353Sdim *
71234353Sdim * 03/09/19: Added support for ACE III & Copernicus II.
72234353Sdim */
73309124Sdim
74309124Sdim#ifdef HAVE_CONFIG_H
75309124Sdim# include "config.h"
76234353Sdim#endif
77224145Sdim
78224145Sdim#if defined(REFCLOCK) && defined(CLOCK_PALISADE)
79193326Sed
80193326Sed#ifdef SYS_WINNT
81193326Sedextern int async_write(int, const void *, unsigned int);
82193326Sed#undef write
83193326Sed#define write(fd, data, octets)	async_write(fd, data, octets)
84193326Sed#endif
85193326Sed
86193326Sed#include "refclock_palisade.h"
87193326Sed
88193326Sed#ifdef DEBUG
89309124Sdimconst char * Tracking_Status[15][15] = {
90309124Sdim	{ "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
91309124Sdim	{"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
92193326Sed	{ "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
93193326Sed	{ "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
94193326Sed	{ "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
95193326Sed#endif
96193326Sed
97193326Sed/*
98193326Sed * Transfer vector
99193326Sed */
100193326Sedstruct refclock refclock_palisade = {
101193326Sed	palisade_start,		/* start up driver */
102193326Sed	palisade_shutdown,	/* shut down driver */
103193326Sed	palisade_poll,		/* transmit poll message */
104193326Sed	noentry,		/* not used  */
105193326Sed	noentry,		/* initialize driver (not used) */
106193326Sed	noentry,		/* not used */
107193326Sed	NOFLAGS			/* not used */
108193326Sed};
109193326Sed
110193326Sedstatic int decode_date(struct refclockproc *pp, const char *cp);
111193326Sed
112193326Sed/* Extract the clock type from the mode setting */
113193326Sed#define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
114193326Sed
115193326Sed/* Supported clock types */
116193326Sed#define CLK_TRIMBLE	0	/* Trimble Palisade */
117193326Sed#define CLK_PRAECIS	1	/* Endrun Technologies Praecis */
118193326Sed#define CLK_THUNDERBOLT	2	/* Trimble Thunderbolt GPS Receiver */
119193326Sed#define CLK_ACUTIME     3	/* Trimble Acutime Gold */
120193326Sed#define CLK_ACUTIMEB    4	/* Trimble Actutime Gold Port B */
121193326Sed#define CLK_RESOLUTION  5	/* Trimble Resolution Receivers */
122193326Sed#define CLK_ACE		6	/* Trimble ACE III */
123193326Sed#define CLK_COPERNICUS	7	/* Trimble Copernicus II */
124193326Sed
125234353Sdimint praecis_msg;
126234353Sdimstatic void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
127234353Sdim
128234353Sdim/* These routines are for sending packets to the Thunderbolt receiver
129309124Sdim * They are taken from Markus Prosch
130309124Sdim */
131309124Sdim
132234353Sdim/*
133234353Sdim * sendcmd - Build data packet for sending
134193326Sed */
135static void
136sendcmd (
137	struct packettx *buffer,
138	int c
139	)
140{
141	*buffer->data = DLE;
142	*(buffer->data + 1) = (unsigned char)c;
143	buffer->size = 2;
144}
145
146/*
147 * sendsupercmd - Build super data packet for sending
148 */
149static void
150sendsupercmd (
151	struct packettx *buffer,
152	int c1,
153	int c2
154	)
155{
156	*buffer->data = DLE;
157	*(buffer->data + 1) = (unsigned char)c1;
158	*(buffer->data + 2) = (unsigned char)c2;
159	buffer->size = 3;
160}
161
162/*
163 * sendbyte -
164 */
165static void
166sendbyte (
167	struct packettx *buffer,
168	int b
169	)
170{
171	if (b == DLE)
172		*(buffer->data+buffer->size++) = DLE;
173	*(buffer->data+buffer->size++) = (unsigned char)b;
174}
175
176/*
177 * sendint -
178 */
179static void
180sendint (
181	struct packettx *buffer,
182	int a
183	)
184{
185	sendbyte(buffer, (unsigned char)((a>>8) & 0xff));
186	sendbyte(buffer, (unsigned char)(a & 0xff));
187}
188
189/*
190 * sendetx - Send packet or super packet to the device
191 */
192static int
193sendetx (
194	struct packettx *buffer,
195	int fd
196	)
197{
198	int result;
199
200	*(buffer->data+buffer->size++) = DLE;
201	*(buffer->data+buffer->size++) = ETX;
202	result = write(fd, buffer->data, (unsigned long)buffer->size);
203
204	if (result != -1)
205		return (result);
206	else
207		return (-1);
208}
209
210/*
211 * init_thunderbolt - Prepares Thunderbolt receiver to be used with
212 *		      NTP (also taken from Markus Prosch).
213 */
214static void
215init_thunderbolt (
216	int fd
217	)
218{
219	struct packettx tx;
220
221	tx.size = 0;
222	tx.data = (u_char *) emalloc(100);
223
224	/* set UTC time */
225	sendsupercmd (&tx, 0x8E, 0xA2);
226	sendbyte     (&tx, 0x3);
227	sendetx      (&tx, fd);
228
229	/* activate packets 0x8F-AB and 0x8F-AC */
230	sendsupercmd (&tx, 0x8E, 0xA5);
231	sendint      (&tx, 0x5);
232	sendetx      (&tx, fd);
233
234	free(tx.data);
235}
236
237/*
238 * init_acutime - Prepares Acutime Receiver to be used with NTP
239 */
240static void
241init_acutime (
242	int fd
243	)
244{
245	/* Disable all outputs, Enable Event-Polling on PortA so
246	   we can ask for time packets */
247	struct packettx tx;
248
249	tx.size = 0;
250	tx.data = (u_char *) emalloc(100);
251
252	sendsupercmd(&tx, 0x8E, 0xA5);
253	sendbyte(&tx, 0x02);
254	sendbyte(&tx, 0x00);
255	sendbyte(&tx, 0x00);
256	sendbyte(&tx, 0x00);
257	sendetx(&tx, fd);
258
259	free(tx.data);
260}
261
262/*
263 * init_resolution - Prepares Resolution receiver to be used with NTP
264 */
265static void
266init_resolution (
267	int fd
268	)
269{
270	struct packettx tx;
271
272	tx.size = 0;
273	tx.data = (u_char *) emalloc(100);
274
275	/* set UTC time */
276	sendsupercmd (&tx, 0x8E, 0xA2);
277	sendbyte     (&tx, 0x3);
278	sendetx      (&tx, fd);
279
280	/* squelch PPS output unless locked to at least one satellite */
281	sendsupercmd (&tx, 0x8E, 0x4E);
282	sendbyte     (&tx, 0x3);
283	sendetx      (&tx, fd);
284
285	/* activate packets 0x8F-AB and 0x8F-AC */
286	sendsupercmd (&tx, 0x8E, 0xA5);
287	sendint      (&tx, 0x5);
288	sendetx      (&tx, fd);
289
290	free(tx.data);
291}
292
293/*
294 * palisade_start - open the devices and initialize data for processing
295 */
296static int
297palisade_start (
298	int unit,
299	struct peer *peer
300	)
301{
302	struct palisade_unit *up;
303	struct refclockproc *pp;
304	int fd;
305	char gpsdev[20];
306	struct termios tio;
307	u_int speed;
308
309	snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
310
311	/*
312	 * Open serial port.
313	 */
314	speed = (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232;
315	fd = refclock_open(&peer->srcadr, gpsdev, speed, LDISC_RAW);
316	if (fd <= 0) {
317#ifdef DEBUG
318		printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
319#endif
320		return 0;
321	}
322
323	msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
324		gpsdev);
325
326	if (tcgetattr(fd, &tio) < 0) {
327		msyslog(LOG_ERR,
328			"Palisade(%d) tcgetattr(fd, &tio): %m",unit);
329#ifdef DEBUG
330		printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
331#endif
332		close(fd);
333		return (0);
334	}
335
336	tio.c_cflag |= (PARENB|PARODD);
337	tio.c_iflag &= ~ICRNL;
338
339	/*
340	 * Allocate and initialize unit structure
341	 */
342	up = emalloc_zero(sizeof(*up));
343
344	up->type = CLK_TYPE(peer);
345	switch (up->type) {
346	    case CLK_TRIMBLE:
347		/* Normal mode, do nothing */
348		break;
349	    case CLK_PRAECIS:
350		msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled"
351			,unit);
352		break;
353	    case CLK_THUNDERBOLT:
354		msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled"
355			,unit);
356		tio.c_cflag = (CS8|CLOCAL|CREAD);
357		break;
358	    case CLK_ACUTIME:
359		msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled"
360			,unit);
361		break;
362	    case CLK_RESOLUTION:
363		msyslog(LOG_NOTICE, "Palisade(%d) Resolution mode enabled"
364			,unit);
365		tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
366		break;
367	    case CLK_ACE:
368		msyslog(LOG_NOTICE, "Palisade(%d) ACE III mode enabled"
369			,unit);
370		tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
371		break;
372	    case CLK_COPERNICUS:
373		msyslog(LOG_NOTICE, "Palisade(%d) Copernicus II mode enabled"
374			,unit);
375		/* Must use ORing/ANDing to set/clear c_cflag bits otherwise
376		   CBAUD gets set back to 0. This ought to be an issue for
377		   the other modes above but it seems that the baud rate
378		   defaults to 9600 if CBAUD gets set to 0.                 */
379		tio.c_cflag &= ~(PARENB|PARODD);
380		break;
381	    default:
382		msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit);
383		break;
384	}
385	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
386		msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
387#ifdef DEBUG
388		printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
389#endif
390		close(fd);
391		free(up);
392		return 0;
393	}
394
395	pp = peer->procptr;
396	pp->io.clock_recv = palisade_io;
397	pp->io.srcclock = peer;
398	pp->io.datalen = 0;
399	pp->io.fd = fd;
400	if (!io_addclock(&pp->io)) {
401#ifdef DEBUG
402		printf("Palisade(%d) io_addclock\n",unit);
403#endif
404		close(fd);
405		pp->io.fd = -1;
406		free(up);
407		return (0);
408	}
409
410	/*
411	 * Initialize miscellaneous variables
412	 */
413	pp->unitptr = up;
414	pp->clockdesc = DESCRIPTION;
415
416	peer->precision = PRECISION;
417	peer->sstclktype = CTL_SST_TS_UHF;
418	peer->minpoll = TRMB_MINPOLL;
419	peer->maxpoll = TRMB_MAXPOLL;
420	memcpy((char *)&pp->refid, REFID, 4);
421
422	up->leap_status = 0;
423	up->unit = (short) unit;
424	up->rpt_status = TSIP_PARSED_EMPTY;
425	up->rpt_cnt = 0;
426
427	if (up->type == CLK_THUNDERBOLT)
428		init_thunderbolt(fd);
429	if (up->type == CLK_ACUTIME)
430		init_acutime(fd);
431	if (up->type == CLK_RESOLUTION)
432		init_resolution(fd);
433
434	return 1;
435}
436
437
438/*
439 * palisade_shutdown - shut down the clock
440 */
441static void
442palisade_shutdown (
443	int unit,
444	struct peer *peer
445	)
446{
447	struct palisade_unit *up;
448	struct refclockproc *pp;
449	pp = peer->procptr;
450	up = pp->unitptr;
451	if (-1 != pp->io.fd)
452		io_closeclock(&pp->io);
453	if (NULL != up)
454		free(up);
455}
456
457
458/*
459 * unpack helpers
460 */
461
462static inline uint8_t
463get_u8(
464	const char *cp)
465{
466	return ((const u_char*)cp)[0];
467}
468
469static inline uint16_t
470get_u16(
471	const char *cp)
472{
473	return ((uint16_t)get_u8(cp) << 8) | get_u8(cp + 1);
474}
475
476/*
477 * unpack & fix date (the receiver provides a valid time for 1024 weeks
478 * after 1997-12-14 and therefore folds back in 2017, 2037,...)
479 *
480 * Returns -1 on error, day-of-month + (month * 32) othertwise.
481 */
482int
483decode_date(
484	struct refclockproc *pp,
485	const char          *cp)
486{
487	static int32_t  s_baseday = 0;
488
489	struct calendar jd;
490	int32_t         rd;
491
492	if (0 == s_baseday) {
493		if (!ntpcal_get_build_date(&jd)) {
494			jd.year     = 2015;
495			jd.month    = 1;
496			jd.monthday = 1;
497		}
498		s_baseday = ntpcal_date_to_rd(&jd);
499	}
500
501	/* get date fields and convert to RDN */
502	jd.monthday = get_u8 (  cp  );
503	jd.month    = get_u8 (cp + 1);
504	jd.year     = get_u16(cp + 2);
505	rd = ntpcal_date_to_rd(&jd);
506
507	/* for the paranoid: do reverse calculation and cross-check */
508	ntpcal_rd_to_date(&jd, rd);
509	if ((jd.monthday != get_u8 (  cp  )) ||
510	    (jd.month    != get_u8 (cp + 1)) ||
511	    (jd.year     != get_u16(cp + 2))  )
512		return - 1;
513
514	/* calculate cycle shift to base day and calculate re-folded
515	 * date
516	 *
517	 * One could do a proper modulo calculation here, but a counting
518	 * loop is probably faster for the next few rollovers...
519	 */
520	while (rd < s_baseday)
521		rd += 7*1024;
522	ntpcal_rd_to_date(&jd, rd);
523
524	/* fill refclock structure & indicate success */
525	pp->day  = jd.yearday;
526	pp->year = jd.year;
527	return ((int)jd.month << 5) | jd.monthday;
528}
529
530
531/*
532 * TSIP_decode - decode the TSIP data packets
533 */
534int
535TSIP_decode (
536	struct peer *peer
537	)
538{
539	int st;
540	long   secint;
541	double secs;
542	double secfrac;
543	unsigned short event = 0;
544	int mmday;
545	long tow;
546	uint16_t wn;
547	int GPS_UTC_Offset;
548
549	struct palisade_unit *up;
550	struct refclockproc *pp;
551
552	pp = peer->procptr;
553	up = pp->unitptr;
554
555	/*
556	 * Check the time packet, decode its contents.
557	 * If the timecode has invalid length or is not in
558	 * proper format, declare bad format and exit.
559	 */
560
561	if ((up->type != CLK_THUNDERBOLT) &&
562	    (up->type != CLK_ACUTIME    ) &&
563	    (up->type != CLK_RESOLUTION ) &&
564	    (up->type != CLK_ACE        ) &&
565	    (up->type != CLK_COPERNICUS )   )
566	{
567		if ((up->rpt_buf[0] == (char) 0x41) ||
568		    (up->rpt_buf[0] == (char) 0x46) ||
569		    (up->rpt_buf[0] == (char) 0x54) ||
570		    (up->rpt_buf[0] == (char) 0x4B) ||
571		    (up->rpt_buf[0] == (char) 0x6D)) {
572
573			/* standard time packet - GPS time and GPS week number */
574#ifdef DEBUG
575			printf("Palisade Port B packets detected. Connect to Port A\n");
576#endif
577
578			return 0;
579		}
580	}
581
582	/*
583	 * We cast both to u_char as 0x8f uses the sign bit on a char
584	 */
585	if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
586		/*
587		 * Superpackets
588		 */
589		event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
590		if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
591			/* Ignore Packet */
592			return 0;
593
594		switch (mb(0) & 0xff) {
595
596		    case PACKET_8F0B:
597
598			if (up->polled <= 0)
599				return 0;
600
601			if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
602				break;
603
604#ifdef DEBUG
605			if (debug > 1) {
606				int ts;
607				double lat, lon, alt;
608				lat = getdbl((u_char *) &mb(42)) * R2D;
609				lon = getdbl((u_char *) &mb(50)) * R2D;
610				alt = getdbl((u_char *) &mb(58));
611
612				printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
613				       up->unit, lat,lon,alt);
614				printf("TSIP_decode: unit %d: Sats:",
615				       up->unit);
616				for (st = 66, ts = 0; st <= 73; st++)
617					if (mb(st)) {
618						if (mb(st) > 0) ts++;
619						printf(" %02d", mb(st));
620					}
621				printf(" : Tracking %d\n", ts);
622			}
623#endif
624
625			GPS_UTC_Offset = getint((u_char *) &mb(16));
626			if (GPS_UTC_Offset == 0) { /* Check UTC offset */
627#ifdef DEBUG
628				printf("TSIP_decode: UTC Offset Unknown\n");
629#endif
630				break;
631			}
632
633			secs = getdbl((u_char *) &mb(3));
634			secint = (long) secs;
635			secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
636
637			pp->nsec = (long) (secfrac * 1000000000);
638
639			secint %= 86400;    /* Only care about today */
640			pp->hour = secint / 3600;
641			secint %= 3600;
642			pp->minute = secint / 60;
643			secint %= 60;
644			pp->second = secint % 60;
645
646			mmday = decode_date(pp, &mb(11));
647			if (mmday < 0)
648				break;
649
650#ifdef DEBUG
651			if (debug > 1)
652				printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n",
653				       up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
654				       pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, GPS_UTC_Offset);
655#endif
656			/* Only use this packet when no
657			 * 8F-AD's are being received
658			 */
659
660			if (up->leap_status) {
661				up->leap_status = 0;
662				return 0;
663			}
664
665			return 2;
666			break;
667
668		    case PACKET_NTP:
669			/* Palisade-NTP Packet */
670
671			if (up->rpt_cnt != LENCODE_NTP) /* check length */
672				break;
673
674			up->leap_status = mb(19);
675
676			if (up->polled  <= 0)
677				return 0;
678
679			/* Check Tracking Status */
680			st = mb(18);
681			if (st < 0 || st > 14)
682				st = 14;
683			if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
684#ifdef DEBUG
685				printf("TSIP_decode: Not Tracking Sats : %s\n",
686				       *Tracking_Status[st]);
687#endif
688				refclock_report(peer, CEVNT_BADTIME);
689				up->polled = -1;
690				return 0;
691				break;
692			}
693
694			mmday = decode_date(pp, &mb(14));
695			if (mmday < 0)
696				break;
697			up->month  = (mmday >> 5);  /* Save for LEAP check */
698
699			if ( (up->leap_status & PALISADE_LEAP_PENDING) &&
700			/* Avoid early announce: https://bugs.ntp.org/2773 */
701				(6 == up->month || 12 == up->month) ) {
702				if (up->leap_status & PALISADE_UTC_TIME)
703					pp->leap = LEAP_ADDSECOND;
704				else
705					pp->leap = LEAP_DELSECOND;
706			}
707			else if (up->leap_status)
708				pp->leap = LEAP_NOWARNING;
709
710			else {  /* UTC flag is not set:
711				 * Receiver may have been reset, and lost
712				 * its UTC almanac data */
713				pp->leap = LEAP_NOTINSYNC;
714#ifdef DEBUG
715				printf("TSIP_decode: UTC Almanac unavailable: %d\n",
716				       mb(19));
717#endif
718				refclock_report(peer, CEVNT_BADTIME);
719				up->polled = -1;
720				return 0;
721			}
722
723			pp->nsec = (long) (getdbl((u_char *) &mb(3))
724					   * 1000000000);
725
726			pp->hour = mb(11);
727			pp->minute = mb(12);
728			pp->second = mb(13);
729
730#ifdef DEBUG
731			if (debug > 1)
732				printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n",
733				       up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
734				       pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year,
735				       mb(19), *Tracking_Status[st]);
736#endif
737			return 1;
738			break;
739
740		    case PACKET_8FAC:
741			if (up->polled <= 0)
742				return 0;
743
744			if (up->rpt_cnt != LENCODE_8FAC)/* check length */
745				break;
746
747#ifdef DEBUG
748			if (debug > 1) {
749				double lat, lon, alt;
750				lat = getdbl((u_char *) &mb(36)) * R2D;
751				lon = getdbl((u_char *) &mb(44)) * R2D;
752				alt = getdbl((u_char *) &mb(52));
753
754				printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
755				       up->unit, lat,lon,alt);
756				printf("TSIP_decode: unit %d\n", up->unit);
757			}
758#endif
759			if ( (getint((u_char *) &mb(10)) & 0x80) &&
760			/* Avoid early announce: https://bugs.ntp.org/2773 */
761			    (6 == up->month || 12 == up->month) )
762				pp->leap = LEAP_ADDSECOND;  /* we ASSUME addsecond */
763			else
764				pp->leap = LEAP_NOWARNING;
765
766#ifdef DEBUG
767			if (debug > 1)
768				printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
769				       up->unit, mb(0) & 0xff, pp->leap);
770			if (debug > 1) {
771				printf("Receiver MODE: 0x%02X\n", (u_char)mb(1));
772				if (mb(1) == 0x00)
773					printf("                AUTOMATIC\n");
774				if (mb(1) == 0x01)
775					printf("                SINGLE SATELLITE\n");
776				if (mb(1) == 0x03)
777					printf("                HORIZONTAL(2D)\n");
778				if (mb(1) == 0x04)
779					printf("                FULL POSITION(3D)\n");
780				if (mb(1) == 0x05)
781					printf("                DGPR REFERENCE\n");
782				if (mb(1) == 0x06)
783					printf("                CLOCK HOLD(2D)\n");
784				if (mb(1) == 0x07)
785					printf("                OVERDETERMINED CLOCK\n");
786
787				printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2));
788				if (mb(2) == 0x00)
789					printf("                NORMAL\n");
790				if (mb(2) == 0x01)
791					printf("                POWER-UP\n");
792				if (mb(2) == 0x02)
793					printf("                AUTO HOLDOVER\n");
794				if (mb(2) == 0x03)
795					printf("                MANUAL HOLDOVER\n");
796				if (mb(2) == 0x04)
797					printf("                RECOVERY\n");
798				if (mb(2) == 0x06)
799					printf("                DISCIPLINING DISABLED\n");
800			}
801#endif
802			return 0;
803			break;
804
805		    case PACKET_8FAB:
806			/* Thunderbolt Primary Timing Packet */
807
808			if (up->rpt_cnt != LENCODE_8FAB) /* check length */
809				break;
810
811			if (up->polled  <= 0)
812				return 0;
813
814			GPS_UTC_Offset = getint((u_char *) &mb(7));
815
816			if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
817#ifdef DEBUG
818				printf("TSIP_decode: UTC Offset Unknown\n");
819#endif
820				break;
821			}
822
823
824			if ((mb(9) & 0x1d) == 0x0) {
825				/* if we know the GPS time and the UTC offset,
826				   we expect UTC timing information !!! */
827
828				pp->leap = LEAP_NOTINSYNC;
829				refclock_report(peer, CEVNT_BADTIME);
830				up->polled = -1;
831				return 0;
832			}
833
834			pp->nsec = 0;
835#ifdef DEBUG
836			printf("\nTiming Flags are:\n");
837			printf("Timing flag value is: 0x%X\n", mb(9));
838			if ((mb(9) & 0x01) != 0)
839				printf ("	Getting UTC time\n");
840			else
841				printf ("	Getting GPS time\n");
842			if ((mb(9) & 0x02) != 0)
843				printf ("	PPS is from UTC\n");
844			else
845				printf ("	PPS is from GPS\n");
846			if ((mb(9) & 0x04) != 0)
847				printf ("	Time is not Set\n");
848			else
849				printf ("	Time is Set\n");
850			if ((mb(9) & 0x08) != 0)
851				printf("	I dont have UTC info\n");
852			else
853				printf ("	I have UTC info\n");
854			if ((mb(9) & 0x10) != 0)
855				printf ("	Time is from USER\n\n");
856			else
857				printf ("	Time is from GPS\n\n");
858#endif
859
860			mmday = decode_date(pp, &mb(13));
861			if (mmday < 0)
862				break;
863			tow = getlong((u_char *) &mb(1));
864#ifdef DEBUG
865			if (debug > 1) {
866				printf("pp->day: %d\n", pp->day);
867				printf("TOW: %ld\n", tow);
868				printf("DAY: %d\n", (mmday & 31));
869			}
870#endif
871			pp->hour = mb(12);
872			pp->minute = mb(11);
873			pp->second = mb(10);
874
875
876#ifdef DEBUG
877			if (debug > 1)
878				printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
879				       up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
880				       pp->nsec, (mmday >> 5), (mmday & 31), pp->year);
881#endif
882			return 1;
883			break;
884
885		    default:
886			/* Ignore Packet */
887			return 0;
888		} /* switch */
889	} /* if 8F packets */
890
891	else if (up->rpt_buf[0] == (u_char)0x42) {
892		printf("0x42\n");
893		return 0;
894	}
895	else if (up->rpt_buf[0] == (u_char)0x43) {
896		printf("0x43\n");
897		return 0;
898	}
899	else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){
900		printf("Undocumented 0x41 packet on Thunderbolt\n");
901		return 0;
902	}
903	else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
904#ifdef DEBUG
905		printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0)));
906		printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
907		printf("GPS UTC-GPS Offset: %ld\n", (long)getlong((u_char *) &mb(6)));
908#endif
909		return 0;
910	}
911
912	/* GPS time packet for ACE III or Copernicus II receiver */
913	else if ((up->rpt_buf[0] == PACKET_41) &&
914	         ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) {
915#ifdef DEBUG
916		if ((debug > 1) && (up->type == CLK_ACE))
917			printf("TSIP_decode: Packet 0x41 seen in ACE III mode\n");
918		if ((debug > 1) && (up->type == CLK_COPERNICUS))
919			printf("TSIP_decode: Packet 0x41 seen in Copernicus II mode\n");
920#endif
921		if (up->rpt_cnt != LENCODE_41) { /* check length */
922			refclock_report(peer, CEVNT_BADREPLY);
923			up->polled = -1;
924#ifdef DEBUG
925			printf("TSIP_decode: unit %d: bad packet %02x len %d\n",
926				up->unit, up->rpt_buf[0] & 0xff, up->rpt_cnt);
927#endif
928			return 0;
929		}
930		if (up->polled  <= 0)
931			return 0;
932		tow = (long)getsingle((u_char *) &mb(0));
933		wn = (uint16_t)getint((u_char *) &mb(4));
934		GPS_UTC_Offset = (int)getsingle((u_char *) &mb(6));
935		if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
936#ifdef DEBUG
937			printf("TSIP_decode: UTC Offset Unknown\n");
938#endif
939			refclock_report(peer, CEVNT_BADREPLY);
940			up->polled = -1;
941			return 0;
942		}
943		/* Get date & time from WN & ToW minus offset */
944		{
945			TCivilDate cd;
946			TGpsDatum wd;
947			l_fp ugo; /* UTC-GPS offset, negative number */
948			ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset;
949			ugo.l_uf = 0;
950			wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo);
951			gpscal_to_calendar(&cd, &wd);
952			pp->year = cd.year;
953			pp->day = cd.yearday;
954			pp->hour = cd.hour;
955			pp->minute = cd.minute;
956			pp->second = cd.second;
957			pp->nsec = 0;
958			pp->leap = LEAP_NOWARNING;
959#ifdef DEBUG
960			if (debug > 1)	{
961				printf("GPS TOW: %ld\n", tow);
962				printf("GPS WN: %d\n", wn);
963				printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset);
964				printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
965				       up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
966				       pp->nsec, cd.month, cd.monthday, pp->year);
967			}
968#endif
969		}
970		return 1;
971	}
972
973	/* Health Status for Acutime Receiver */
974	else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
975#ifdef DEBUG
976		if (debug > 1)
977		/* Status Codes */
978			switch (mb(0)) {
979			    case 0x00:
980				printf ("Doing Position Fixes\n");
981				break;
982			    case 0x01:
983				printf ("Do not have GPS time yet\n");
984				break;
985			    case 0x03:
986				printf ("PDOP is too high\n");
987				break;
988			    case 0x08:
989				printf ("No usable satellites\n");
990				break;
991			    case 0x09:
992				printf ("Only 1 usable satellite\n");
993				break;
994			    case 0x0A:
995				printf ("Only 2 usable satellites\n");
996				break;
997			    case 0x0B:
998				printf ("Only 3 usable satellites\n");
999				break;
1000			    case 0x0C:
1001				printf("The Chosen satellite is unusable\n");
1002				break;
1003			}
1004#endif
1005		/* Error Codes */
1006		if (mb(1) != 0)	{
1007
1008			refclock_report(peer, CEVNT_BADTIME);
1009			up->polled = -1;
1010#ifdef DEBUG
1011			if (debug > 1) {
1012				if (mb(1) & 0x01)
1013					printf ("Signal Processor Error, reset unit.\n");
1014				if (mb(1) & 0x02)
1015					printf ("Alignment error, channel or chip 1, reset unit.\n");
1016				if (mb(1) & 0x03)
1017					printf ("Alignment error, channel or chip 2, reset unit.\n");
1018				if (mb(1) & 0x04)
1019					printf ("Antenna feed line fault (open or short)\n");
1020				if (mb(1) & 0x05)
1021					printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
1022			}
1023#endif
1024
1025		return 0;
1026		}
1027	}
1028
1029	/* Health Status for Copernicus II Receiver */
1030	else if ((up->rpt_buf[0] == PACKET_46) && (up->type == CLK_COPERNICUS)) {
1031#ifdef DEBUG
1032		if (debug > 1)
1033		/* Status Codes */
1034			switch (mb(0)) {
1035			    case 0x00:
1036				printf ("Doing Position Fixes\n");
1037				break;
1038			    case 0x01:
1039				printf ("Do not have GPS time yet\n");
1040				break;
1041			    case 0x03:
1042				printf ("PDOP is too high\n");
1043				break;
1044			    case 0x04:
1045				printf("The Chosen satellite is unusable\n");
1046				break;
1047			    case 0x08:
1048				printf ("No usable satellites\n");
1049				break;
1050			    case 0x09:
1051				printf ("Only 1 usable satellite\n");
1052				break;
1053			    case 0x0A:
1054				printf ("Only 2 usable satellites\n");
1055				break;
1056			    case 0x0B:
1057				printf ("Only 3 usable satellites\n");
1058				break;
1059			}
1060#endif
1061		/* Error Codes */
1062		if ((mb(1) & 0x3E) != 0) {  /* Don't regard bits 0 and 6 as errors */
1063			refclock_report(peer, CEVNT_BADTIME);
1064			up->polled = -1;
1065#ifdef DEBUG
1066			if (debug > 1) {
1067				if ((mb(1) & 0x18) == 0x08)
1068					printf ("Antenna feed line fault (open)\n");
1069				if ((mb(1) & 0x18) == 0x18)
1070					printf ("Antenna feed line fault (short)\n");
1071			}
1072#endif
1073		}
1074		return 0;
1075	}
1076
1077	/* Other packets output by ACE III & Copernicus II Receivers, dropped silently */
1078	else if (((up->rpt_buf[0] == (char) 0x4A) ||
1079		  (up->rpt_buf[0] == (char) 0x4B) ||
1080		  (up->rpt_buf[0] == (char) 0x56) ||
1081		  (up->rpt_buf[0] == (char) 0x5F) ||
1082		  (up->rpt_buf[0] == (char) 0x6D) ||
1083		  (up->rpt_buf[0] == (char) 0x82) ||
1084		  (up->rpt_buf[0] == (char) 0x84)) &&
1085		 ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) {
1086#ifdef DEBUG
1087		if ((debug > 1) && (up->type == CLK_ACE))
1088			printf("TSIP_decode: Packet 0x%2x seen in ACE III mode\n", (up->rpt_buf[0] & 0XFF));
1089		if ((debug > 1) && (up->type == CLK_COPERNICUS))
1090			printf("TSIP_decode: Packet 0x%2x seen in Copernicus II mode\n", (up->rpt_buf[0] & 0XFF));
1091#endif
1092		return 0;
1093	}
1094
1095	else if (up->rpt_buf[0] == 0x54)
1096		return 0;
1097
1098	else if (up->rpt_buf[0] == PACKET_6D) {
1099#ifdef DEBUG
1100		int sats;
1101
1102		if ((mb(0) & 0x01) && (mb(0) & 0x02))
1103			printf("2d Fix Dimension\n");
1104		if (mb(0) & 0x04)
1105			printf("3d Fix Dimension\n");
1106
1107		if (mb(0) & 0x08)
1108			printf("Fix Mode is MANUAL\n");
1109		else
1110			printf("Fix Mode is AUTO\n");
1111
1112		sats = mb(0) & 0xF0;
1113		sats = sats >> 4;
1114		printf("Tracking %d Satellites\n", sats);
1115#endif
1116		return 0;
1117	} /* else if not super packet */
1118	refclock_report(peer, CEVNT_BADREPLY);
1119	up->polled = -1;
1120#ifdef DEBUG
1121	printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
1122	       up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
1123	       event, up->rpt_cnt);
1124#endif
1125	return 0;
1126}
1127
1128/*
1129 * palisade__receive - receive data from the serial interface
1130 */
1131
1132static void
1133palisade_receive (
1134	struct peer * peer
1135	)
1136{
1137	struct palisade_unit *up;
1138	struct refclockproc *pp;
1139
1140	/*
1141	 * Initialize pointers and read the timecode and timestamp.
1142	 */
1143	pp = peer->procptr;
1144	up = pp->unitptr;
1145
1146	if (! TSIP_decode(peer)) return;
1147
1148	if (up->polled <= 0)
1149		return;   /* no poll pending, already received or timeout */
1150
1151	up->polled = 0;  /* Poll reply received */
1152	pp->lencode = 0; /* clear time code */
1153#ifdef DEBUG
1154	if (debug)
1155		printf(
1156			"palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
1157			up->unit, pp->year, pp->day, pp->hour, pp->minute,
1158			pp->second, pp->nsec);
1159#endif
1160
1161	/*
1162	 * Process the sample
1163	 * Generate timecode: YYYY DoY HH:MM:SS.microsec
1164	 * report and process
1165	 */
1166
1167	snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
1168		 "%4d %03d %02d:%02d:%02d.%09ld",
1169		 pp->year, pp->day,
1170		 pp->hour,pp->minute, pp->second, pp->nsec);
1171	pp->lencode = 24;
1172
1173	if (!refclock_process(pp)) {
1174		refclock_report(peer, CEVNT_BADTIME);
1175
1176#ifdef DEBUG
1177		printf("palisade_receive: unit %d: refclock_process failed!\n",
1178		       up->unit);
1179#endif
1180		return;
1181	}
1182
1183	record_clock_stats(&peer->srcadr, pp->a_lastcode);
1184
1185#ifdef DEBUG
1186	if (debug)
1187		printf("palisade_receive: unit %d: %s\n",
1188		       up->unit, prettydate(&pp->lastrec));
1189#endif
1190	pp->lastref = pp->lastrec;
1191	refclock_receive(peer);
1192}
1193
1194
1195/*
1196 * palisade_poll - called by the transmit procedure
1197 *
1198 */
1199static void
1200palisade_poll (
1201	int unit,
1202	struct peer *peer
1203	)
1204{
1205	struct palisade_unit *up;
1206	struct refclockproc *pp;
1207
1208	pp = peer->procptr;
1209	up = pp->unitptr;
1210
1211	pp->polls++;
1212	if (up->polled > 0) /* last reply never arrived or error */
1213		refclock_report(peer, CEVNT_TIMEOUT);
1214
1215	up->polled = 2; /* synchronous packet + 1 event */
1216
1217#ifdef DEBUG
1218	if (debug)
1219		printf("palisade_poll: unit %d: polling %s\n", unit,
1220		       (pp->sloppyclockflag & CLK_FLAG2) ?
1221		       "synchronous packet" : "event");
1222#endif
1223
1224	if (pp->sloppyclockflag & CLK_FLAG2)
1225		return;  /* using synchronous packet input */
1226
1227	if(up->type == CLK_PRAECIS) {
1228		if (write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) {
1229			msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
1230		} else {
1231			praecis_msg = 1;
1232			return;
1233		}
1234	}
1235
1236	if (HW_poll(pp) < 0)
1237		refclock_report(peer, CEVNT_FAULT);
1238}
1239
1240static void
1241praecis_parse (
1242	struct recvbuf *rbufp,
1243	struct peer *peer
1244	)
1245{
1246	static char buf[100];
1247	static int p = 0;
1248	struct refclockproc *pp;
1249
1250	pp = peer->procptr;
1251
1252	if (p + rbufp->recv_length >= sizeof buf) {
1253		struct palisade_unit *up;
1254		up = pp->unitptr;
1255
1256		/*
1257		 * We COULD see if there is a \r\n in the incoming
1258		 * buffer before it overflows, and then process the
1259		 * current line.
1260		 *
1261		 * Similarly, if we already have a hunk of data that
1262		 * we're now flushing, that will cause the line of
1263		 * data we're in the process of collecting to be garbage.
1264		 *
1265		 * Since we now check for this overflow and log when it
1266		 * happens, we're now in a better place to easily see
1267		 * what's going on and perhaps better choices can be made.
1268		 */
1269
1270		/* Do we need to log the size of the overflow? */
1271		msyslog(LOG_ERR, "Palisade(%d) praecis_parse(): input buffer overflow",
1272			up->unit);
1273
1274		p = 0;
1275		praecis_msg = 0;
1276
1277		refclock_report(peer, CEVNT_BADREPLY);
1278
1279		return;
1280	}
1281
1282	memcpy(buf+p, rbufp->recv_buffer, rbufp->recv_length);
1283	p += rbufp->recv_length;
1284
1285	if (   p >= 2
1286	    && buf[p-2] == '\r'
1287	    && buf[p-1] == '\n') {
1288		buf[p-2] = '\0';
1289		record_clock_stats(&peer->srcadr, buf);
1290
1291		p = 0;
1292		praecis_msg = 0;
1293
1294		if (HW_poll(pp) < 0) {
1295			refclock_report(peer, CEVNT_FAULT);
1296		}
1297	}
1298	return;
1299}
1300
1301static void
1302palisade_io (
1303	struct recvbuf *rbufp
1304	)
1305{
1306	/*
1307	 * Initialize pointers and read the timecode and timestamp.
1308	 */
1309	struct palisade_unit *up;
1310	struct refclockproc *pp;
1311	struct peer *peer;
1312
1313	char * c, * d;
1314
1315	peer = rbufp->recv_peer;
1316	pp = peer->procptr;
1317	up = pp->unitptr;
1318
1319	if(up->type == CLK_PRAECIS) {
1320		if(praecis_msg) {
1321			praecis_parse(rbufp,peer);
1322			return;
1323		}
1324	}
1325
1326	c = (char *) &rbufp->recv_space;
1327	d = c + rbufp->recv_length;
1328
1329	while (c != d) {
1330
1331		/* Build time packet */
1332		switch (up->rpt_status) {
1333
1334		    case TSIP_PARSED_DLE_1:
1335			switch (*c)
1336			{
1337			    case 0:
1338			    case DLE:
1339			    case ETX:
1340				up->rpt_status = TSIP_PARSED_EMPTY;
1341				break;
1342
1343			    default:
1344				up->rpt_status = TSIP_PARSED_DATA;
1345				/* save packet ID */
1346				up->rpt_buf[0] = *c;
1347				break;
1348			}
1349			break;
1350
1351		    case TSIP_PARSED_DATA:
1352			if (*c == DLE)
1353				up->rpt_status = TSIP_PARSED_DLE_2;
1354			else
1355				mb(up->rpt_cnt++) = *c;
1356			break;
1357
1358		    case TSIP_PARSED_DLE_2:
1359			if (*c == DLE) {
1360				up->rpt_status = TSIP_PARSED_DATA;
1361				mb(up->rpt_cnt++) =
1362				    *c;
1363			}
1364			else if (*c == ETX)
1365				up->rpt_status = TSIP_PARSED_FULL;
1366			else 	{
1367				/* error: start new report packet */
1368				up->rpt_status = TSIP_PARSED_DLE_1;
1369				up->rpt_buf[0] = *c;
1370			}
1371			break;
1372
1373		    case TSIP_PARSED_FULL:
1374		    case TSIP_PARSED_EMPTY:
1375		    default:
1376			if ( *c != DLE)
1377				up->rpt_status = TSIP_PARSED_EMPTY;
1378			else
1379				up->rpt_status = TSIP_PARSED_DLE_1;
1380			break;
1381		}
1382
1383		c++;
1384
1385		if (up->rpt_status == TSIP_PARSED_DLE_1) {
1386			up->rpt_cnt = 0;
1387			if (pp->sloppyclockflag & CLK_FLAG2)
1388				/* stamp it */
1389				get_systime(&pp->lastrec);
1390		}
1391		else if (up->rpt_status == TSIP_PARSED_EMPTY)
1392			up->rpt_cnt = 0;
1393
1394		else if (up->rpt_cnt > BMAX)
1395			up->rpt_status =TSIP_PARSED_EMPTY;
1396
1397		if (up->rpt_status == TSIP_PARSED_FULL)
1398			palisade_receive(peer);
1399
1400	} /* while chars in buffer */
1401}
1402
1403
1404/*
1405 * Trigger the Palisade's event input, which is driven off the RTS
1406 *
1407 * Take a system time stamp to match the GPS time stamp.
1408 *
1409 */
1410long
1411HW_poll (
1412	struct refclockproc * pp 	/* pointer to unit structure */
1413	)
1414{
1415	int x;	/* state before & after RTS set */
1416	struct palisade_unit *up;
1417	struct packettx tx;
1418
1419	up = pp->unitptr;
1420
1421	if (up->type == CLK_ACE) {
1422		/* Poll by sending a 0x21 command */
1423		tx.size = 0;
1424		tx.data = (u_char *) emalloc(100);
1425		sendcmd (&tx, 0x21);
1426		sendetx (&tx, pp->io.fd);
1427		free(tx.data);
1428	} else {
1429
1430	/* read the current status, so we put things back right */
1431	if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1432		DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1433			up->unit));
1434		msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
1435			up->unit);
1436		return -1;
1437	}
1438
1439	x |= TIOCM_RTS;        /* turn on RTS  */
1440
1441	/* Edge trigger */
1442	if (up->type == CLK_ACUTIME)
1443		if (write (pp->io.fd, "", 1) != 1)
1444			msyslog(LOG_WARNING,
1445				"Palisade(%d) HW_poll: failed to send trigger: %m",
1446				up->unit);
1447
1448	if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
1449#ifdef DEBUG
1450		if (debug)
1451			printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1452#endif
1453		msyslog(LOG_ERR,
1454			"Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
1455			up->unit);
1456		return -1;
1457	}
1458
1459	x &= ~TIOCM_RTS;        /* turn off RTS  */
1460
1461	} /* (up->type != CLK_ACE) */
1462
1463	/* poll timestamp */
1464	get_systime(&pp->lastrec);
1465
1466	if (up->type != CLK_ACE) {
1467	if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1468#ifdef DEBUG
1469		if (debug)
1470			printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1471#endif
1472		msyslog(LOG_ERR,
1473			"Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
1474			up->unit);
1475		return -1;
1476	}
1477	}
1478
1479	return 0;
1480}
1481
1482/*
1483 * copy/swap a big-endian palisade double into a host double
1484 */
1485static double
1486getdbl (
1487	u_char *bp
1488	)
1489{
1490#ifdef WORDS_BIGENDIAN
1491	double out;
1492
1493	memcpy(&out, bp, sizeof(out));
1494	return out;
1495#else
1496	union {
1497		u_char ch[8];
1498		u_int32 u32[2];
1499	} ui;
1500
1501	union {
1502		double out;
1503		u_int32 u32[2];
1504	} uo;
1505
1506	memcpy(ui.ch, bp, sizeof(ui.ch));
1507	/* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1508	uo.u32[0] = ntohl(ui.u32[1]);
1509	/* most-significant 32 bits from swapped bp[0] to bp[3] */
1510	uo.u32[1] = ntohl(ui.u32[0]);
1511
1512	return uo.out;
1513#endif
1514}
1515
1516/*
1517 * copy/swap a big-endian palisade short into a host short
1518 */
1519static short
1520getint (
1521	u_char *bp
1522	)
1523{
1524	u_short us;
1525
1526	memcpy(&us, bp, sizeof(us));
1527	return (short)ntohs(us);
1528}
1529
1530/*
1531 * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1532 */
1533static int32
1534getlong(
1535	u_char *bp
1536	)
1537{
1538	u_int32 u32;
1539
1540	memcpy(&u32, bp, sizeof(u32));
1541	return (int32)(u_int32)ntohl(u32);
1542}
1543
1544/*
1545 * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int
1546 */
1547static int32
1548getsingle(
1549	u_char *bp
1550	)
1551{
1552	u_int32 mantissa;
1553	int8_t exponent;
1554	uint8_t sign, exp_field;
1555	int32 res;
1556
1557	memcpy(&mantissa, bp, sizeof(mantissa));
1558	mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000;
1559	exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7);
1560	exponent = (int8_t)exp_field - 127;
1561	sign = ((uint8_t)bp[0] >> 7);
1562	if (exponent > 23)
1563		res = (int32)(mantissa << (exponent - 23));
1564	else
1565		res = (int32)(mantissa >> (23 - exponent));
1566	return sign ? -res : res;
1567}
1568
1569#else	/* REFCLOCK && CLOCK_PALISADE*/
1570NONEMPTY_TRANSLATION_UNIT
1571#endif
1572