xref: /freebsd/contrib/ntp/ntpd/refclock_palisade.c (revision 17d6c636720d00f77e5d098daf4c278f89d84f7b)
1 /*
2  * This software was developed by the Software and Component Technologies
3  * group of Trimble Navigation, Ltd.
4  *
5  * Copyright (c) 1997, 1998, 1999, 2000  Trimble Navigation Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *    This product includes software developed by Trimble Navigation, Ltd.
19  * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
20  *    promote products derived from this software without specific prior
21  *    written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*
37  * refclock_palisade - clock driver for the Trimble Palisade GPS
38  * timing receiver
39  *
40  * For detailed information on this program, please refer to the html
41  * Refclock 29 page accompanying the NTP distribution.
42  *
43  * for questions / bugs / comments, contact:
44  * sven_dietrich@trimble.com
45  *
46  * Sven-Thorsten Dietrich
47  * 645 North Mary Avenue
48  * Post Office Box 3642
49  * Sunnyvale, CA 94088-3642
50  *
51  * Version 2.45; July 14, 1999
52  *
53  */
54 
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
60 
61 #include "refclock_palisade.h"
62 /* Table to get from month to day of the year */
63 const int days_of_year [12] = {
64 	0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
65 };
66 
67 #ifdef DEBUG
68 const char * Tracking_Status[15][15] = {
69         	{ "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
70         	{"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
71         	{ "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
72         	{ "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
73         	{ "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
74 #endif
75 
76 /*
77  * Transfer vector
78  */
79 struct refclock refclock_palisade = {
80 	palisade_start,		/* start up driver */
81 	palisade_shutdown,	/* shut down driver */
82 	palisade_poll,		/* transmit poll message */
83 	noentry,		/* not used  */
84 	noentry,		/* initialize driver (not used) */
85 	noentry,		/* not used */
86 	NOFLAGS			/* not used */
87 };
88 
89 int day_of_year P((char *dt));
90 
91 /*
92  * palisade_start - open the devices and initialize data for processing
93  */
94 static int
95 palisade_start (
96 #ifdef PALISADE
97 	unit, peer
98 	)
99 	int unit;
100 	struct peer *peer;
101 #else /* ANSI */
102 	int unit,
103 	struct peer *peer
104 	)
105 #endif
106 {
107 	struct palisade_unit *up;
108 	struct refclockproc *pp;
109 	int fd;
110 	char gpsdev[20];
111 
112 	struct termios tio;
113 #ifdef SYS_WINNT
114 	(void) sprintf(gpsdev, "COM%d:", unit);
115 #else
116 	(void) sprintf(gpsdev, DEVICE, unit);
117 #endif
118 	/*
119 	 * Open serial port.
120 	 */
121 #if defined PALISADE
122 	 fd = open(gpsdev, O_RDWR
123 #ifdef O_NONBLOCK
124                   | O_NONBLOCK
125 #endif
126                   );
127 #else /* NTP 4.x */
128 	fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
129 #endif
130 	if (fd <= 0) {
131 #ifdef DEBUG
132 		printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
133 #endif
134 		return 0;
135 	}
136 
137 	msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
138 		gpsdev);
139 
140 #if defined PALISADE
141         tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
142         tio.c_iflag = (IGNBRK);
143         tio.c_oflag = (0);
144         tio.c_lflag = (0);
145 
146         if (cfsetispeed(&tio, SPEED232) == -1) {
147                 msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
148 #ifdef DEBUG
149                 printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
150 #endif
151                 return 0;
152         }
153         if (cfsetospeed(&tio, SPEED232) == -1) {
154 #ifdef DEBUG
155                 printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
156 #endif
157                 msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
158                 return 0;
159         }
160 #else /* NTP 4.x */
161         if (tcgetattr(fd, &tio) < 0) {
162                 msyslog(LOG_ERR,
163 			"Palisade(%d) tcgetattr(fd, &tio): %m",unit);
164 #ifdef DEBUG
165                 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
166 #endif
167                 return (0);
168         }
169 
170         tio.c_cflag |= (PARENB|PARODD);
171         tio.c_iflag &= ~ICRNL;
172 #endif /*  NTP 4.x */
173 
174 	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
175                 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
176 #ifdef DEBUG
177                 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
178 #endif
179                 return 0;
180         }
181 
182 	/*
183 	 * Allocate and initialize unit structure
184 	 */
185 	up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
186 
187 	if (!(up)) {
188                 msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
189 #ifdef DEBUG
190                 printf("Palisade(%d) emalloc\n",unit);
191 #endif
192 		(void) close(fd);
193 		return (0);
194 	}
195 
196 	memset((char *)up, 0, sizeof(struct palisade_unit));
197 
198 	pp = peer->procptr;
199 	pp->io.clock_recv = palisade_io;
200 	pp->io.srcclock = (caddr_t)peer;
201 	pp->io.datalen = 0;
202 	pp->io.fd = fd;
203 	if (!io_addclock(&pp->io)) {
204 #ifdef DEBUG
205                 printf("Palisade(%d) io_addclock\n",unit);
206 #endif
207 		(void) close(fd);
208 		free(up);
209 		return (0);
210 	}
211 
212 	/*
213 	 * Initialize miscellaneous variables
214 	 */
215 	pp->unitptr = (caddr_t)up;
216 	pp->clockdesc = DESCRIPTION;
217 
218 	peer->precision = PRECISION;
219 	peer->sstclktype = CTL_SST_TS_UHF;
220 	peer->minpoll = TRMB_MINPOLL;
221 	peer->maxpoll = TRMB_MAXPOLL;
222 	memcpy((char *)&pp->refid, REFID, 4);
223 
224 	up->leap_status = 0;
225 	up->unit = (short) unit;
226 	up->rpt_status = TSIP_PARSED_EMPTY;
227     	up->rpt_cnt = 0;
228 
229 	return 1;
230 }
231 
232 
233 /*
234  * palisade_shutdown - shut down the clock
235  */
236 static void
237 palisade_shutdown (
238 #ifdef PALISADE
239 	unit, peer
240 	)
241 	int unit;
242 	struct peer *peer;
243 #else /* ANSI */
244 	int unit,
245 	struct peer *peer
246 	)
247 #endif
248 {
249 	struct palisade_unit *up;
250 	struct refclockproc *pp;
251 	pp = peer->procptr;
252 	up = (struct palisade_unit *)pp->unitptr;
253 	io_closeclock(&pp->io);
254 	free(up);
255 }
256 
257 
258 
259 /*
260  * unpack_date - get day and year from date
261  */
262 int
263 day_of_year (
264 #ifdef PALISADE
265 	dt
266 	)
267 	char * dt;
268 #else
269 	char * dt
270 	)
271 #endif
272 {
273 	int day, mon, year;
274 
275 	mon = dt[1];
276        /* Check month is inside array bounds */
277        if ((mon < 1) || (mon > 12))
278 		return -1;
279 
280 	day = dt[0] + days_of_year[mon - 1];
281 	year = getint((u_char *) (dt + 2));
282 
283 	if ( !(year % 4) && ((year % 100) ||
284 		(!(year % 100) && !(year%400)))
285 			&&(mon > 2))
286 			day ++; /* leap year and March or later */
287 
288 	return day;
289 }
290 
291 
292 /*
293  * TSIP_decode - decode the TSIP data packets
294  */
295 int
296 TSIP_decode (
297 #ifdef PALISADE
298 	peer
299 	)
300 	struct peer *peer;
301 #else
302 	struct peer *peer
303 	)
304 #endif
305 {
306 	int st;
307 	long   secint;
308 	double secs;
309 	double secfrac;
310 	unsigned short event = 0;
311 
312 	struct palisade_unit *up;
313 	struct refclockproc *pp;
314 
315 	pp = peer->procptr;
316 	up = (struct palisade_unit *)pp->unitptr;
317 
318 	/*
319 	 * Check the time packet, decode its contents.
320 	 * If the timecode has invalid length or is not in
321 	 * proper format, declare bad format and exit.
322 	 */
323 
324 	if ((up->rpt_buf[0] == (char) 0x41) ||
325 		(up->rpt_buf[0] == (char) 0x46) ||
326 		(up->rpt_buf[0] == (char) 0x54) ||
327 		(up->rpt_buf[0] == (char) 0x4B) ||
328 		(up->rpt_buf[0] == (char) 0x6D)) {
329 
330 	/* standard time packet - GPS time and GPS week number */
331 #ifdef DEBUG
332 			printf("Palisade Port B packets detected. Connect to Port A\n");
333 #endif
334 
335 		return 0;
336 	}
337 
338 	if (up->rpt_buf[0] == (char) 0x8f) {
339 	/*
340 	 * Superpackets
341 	 */
342 	   event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
343 	   if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
344 		/* Ignore Packet */
345 			return 0;
346 
347 	   switch (mb(0) & 0xff) {
348 	     int GPS_UTC_Offset;
349 	     case PACKET_8F0B:
350 
351 		if (up->polled <= 0)
352 			return 0;
353 
354 		if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
355 			break;
356 
357 #ifdef DEBUG
358 if (debug > 1) {
359 		int ts;
360 		double lat, lon, alt;
361 		lat = getdbl((u_char *) &mb(42)) * R2D;
362 		lon = getdbl((u_char *) &mb(50)) * R2D;
363 		alt = getdbl((u_char *) &mb(58));
364 
365   		printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
366 				up->unit, lat,lon,alt);
367   		printf("TSIP_decode: unit %d: Sats:", up->unit);
368 		for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
369 			if (mb(st) > 0) ts++;
370 			printf(" %02d", mb(st));
371 		}
372 		printf(" : Tracking %d\n", ts);
373 	}
374 #endif
375 
376 		GPS_UTC_Offset = getint((u_char *) &mb(16));
377 		if (GPS_UTC_Offset == 0) { /* Check UTC offset */
378 #ifdef DEBUG
379 			 printf("TSIP_decode: UTC Offset Unknown\n");
380 #endif
381 			break;
382 		}
383 
384 		secs = getdbl((u_char *) &mb(3));
385 		secint = (long) secs;
386 		secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
387 
388 		pp->usec = (long) (secfrac * 1000000);
389 
390 		secint %= 86400;    /* Only care about today */
391 		pp->hour = secint / 3600;
392 		secint %= 3600;
393 		pp->minute = secint / 60;
394 		secint %= 60;
395 		pp->second = secint % 60;
396 
397 		if ((pp->day = day_of_year(&mb(11))) < 0) break;
398 
399 		pp->year = getint((u_char *) &mb(13));
400 
401 #ifdef DEBUG
402 	if (debug > 1)
403 		printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
404  			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
405 			pp->second, pp->usec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
406 #endif
407 		/* Only use this packet when no
408 		 * 8F-AD's are being received
409 		 */
410 
411 		if (up->leap_status) {
412 			up->leap_status = 0;
413 			return 0;
414 		}
415 
416 		return 2;
417 		break;
418 
419 	  case PACKET_NTP:
420 		/* Palisade-NTP Packet */
421 
422 		if (up->rpt_cnt != LENCODE_NTP) /* check length */
423 			break;
424 
425 		up->leap_status = mb(19);
426 
427 		if (up->polled  <= 0)
428 			return 0;
429 
430 		/* Check Tracking Status */
431 		st = mb(18);
432 		if (st < 0 || st > 14) st = 14;
433 		if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
434 #ifdef DEBUG
435 		 printf("TSIP_decode: Not Tracking Sats : %s\n",
436 				*Tracking_Status[st]);
437 #endif
438 			refclock_report(peer, CEVNT_BADTIME);
439 			up->polled = -1;
440 			return 0;
441 			break;
442 		}
443 
444 		if (up->leap_status & PALISADE_LEAP_PENDING) {
445 			if (up->leap_status & PALISADE_UTC_TIME)
446 				pp->leap = LEAP_ADDSECOND;
447 			else
448 				pp->leap = LEAP_DELSECOND;
449 		}
450 		else if (up->leap_status)
451 			pp->leap = LEAP_NOWARNING;
452 
453 		else {  /* UTC flag is not set:
454 			 * Receiver may have been reset, and lost
455 			 * its UTC almanac data */
456 			pp->leap = LEAP_NOTINSYNC;
457 #ifdef DEBUG
458 			 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
459 				mb(19));
460 #endif
461 			refclock_report(peer, CEVNT_BADTIME);
462 			up->polled = -1;
463 			return 0;
464 		}
465 
466 		pp->usec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
467 
468 		if ((pp->day = day_of_year(&mb(14))) < 0)
469 			break;
470 		pp->year = getint((u_char *) &mb(16));
471 		pp->hour = mb(11);
472 		pp->minute = mb(12);
473 		pp->second = mb(13);
474 
475 #ifdef DEBUG
476 	if (debug > 1)
477 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
478  			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
479 			pp->second, pp->usec, mb(15), mb(14), pp->year,
480 			mb(19), *Tracking_Status[st]);
481 #endif
482 		return 1;
483 		break;
484 
485 	  default:
486 		/* Ignore Packet */
487 		return 0;
488 	  } /* switch */
489 	}/* if 8F packets */
490 
491 	refclock_report(peer, CEVNT_BADREPLY);
492 	up->polled = -1;
493 #ifdef DEBUG
494 	printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
495 		   up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
496 			event, up->rpt_cnt);
497 #endif
498 	return 0;
499 }
500 
501 /*
502  * palisade__receive - receive data from the serial interface
503  */
504 
505 static void
506 palisade_receive (
507 #ifdef PALISADE
508 	peer
509 	)
510 	struct peer * peer;
511 #else /* ANSI */
512 	struct peer * peer
513 	)
514 #endif
515 {
516 	struct palisade_unit *up;
517 	struct refclockproc *pp;
518 
519 	/*
520 	 * Initialize pointers and read the timecode and timestamp.
521 	 */
522 	pp = peer->procptr;
523 	up = (struct palisade_unit *)pp->unitptr;
524 
525 	if (! TSIP_decode(peer)) return;
526 
527 	if (up->polled <= 0)
528 	    return;   /* no poll pending, already received or timeout */
529 
530 	up->polled = 0;  /* Poll reply received */
531 	pp->lencode = 0; /* clear time code */
532 #ifdef DEBUG
533 	if (debug)
534 		printf(
535 	"palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
536 			up->unit, pp->year, pp->day, pp->hour, pp->minute,
537 			pp->second, pp->usec);
538 #endif
539 
540 	/*
541 	 * Process the sample
542 	 * Generate timecode: YYYY DoY HH:MM:SS.microsec
543 	 * report and process
544 	 */
545 
546 	(void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
547 		   pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->usec);
548 	pp->lencode = 24;
549 
550 #ifdef PALISADE
551     	pp->lasttime = current_time;
552 #endif
553 	if (!refclock_process(pp
554 #ifdef PALISADE
555 		, PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
556 #endif
557 		)) {
558 		refclock_report(peer, CEVNT_BADTIME);
559 
560 #ifdef DEBUG
561 		printf("palisade_receive: unit %d: refclock_process failed!\n",
562 			up->unit);
563 #endif
564 		return;
565 	}
566 
567 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
568 
569 #ifdef DEBUG
570 	if (debug)
571 	    printf("palisade_receive: unit %d: %s\n",
572 		   up->unit, prettydate(&pp->lastrec));
573 #endif
574 
575 	refclock_receive(peer
576 #ifdef PALISADE
577 		, &pp->offset, 0, pp->dispersion,
578               &pp->lastrec, &pp->lastrec, pp->leap
579 #endif
580 		);
581 }
582 
583 
584 /*
585  * palisade_poll - called by the transmit procedure
586  *
587  */
588 static void
589 palisade_poll (
590 #ifdef PALISADE
591 	unit, peer
592 	)
593 	int unit;
594 	struct peer *peer;
595 #else
596 	int unit,
597 	struct peer *peer
598 	)
599 #endif
600 {
601 	struct palisade_unit *up;
602 	struct refclockproc *pp;
603 
604 	pp = peer->procptr;
605 	up = (struct palisade_unit *)pp->unitptr;
606 
607 	pp->polls++;
608 	if (up->polled > 0) /* last reply never arrived or error */
609 	    refclock_report(peer, CEVNT_TIMEOUT);
610 
611 	up->polled = 2; /* synchronous packet + 1 event */
612 
613 #ifdef DEBUG
614 	if (debug)
615 	    printf("palisade_poll: unit %d: polling %s\n", unit,
616 		   (pp->sloppyclockflag & CLK_FLAG2) ?
617 			"synchronous packet" : "event");
618 #endif
619 
620 	if (pp->sloppyclockflag & CLK_FLAG2)
621 	    return;  /* using synchronous packet input */
622 
623 	if (HW_poll(pp) < 0)
624 	    refclock_report(peer, CEVNT_FAULT);
625 }
626 
627 
628 static void
629 palisade_io (
630 #ifdef PALISADE
631 	rbufp
632 	)
633 	struct recvbuf *rbufp;
634 #else /* ANSI */
635 	struct recvbuf *rbufp
636 	)
637 #endif
638 {
639 	/*
640 	 * Initialize pointers and read the timecode and timestamp.
641 	 */
642 	struct palisade_unit *up;
643 	struct refclockproc *pp;
644 	struct peer *peer;
645 
646 	char * c, * d;
647 
648 	peer = (struct peer *)rbufp->recv_srcclock;
649 	pp = peer->procptr;
650 	up = (struct palisade_unit *)pp->unitptr;
651 
652 	c = (char *) &rbufp->recv_space;
653 	d = c + rbufp->recv_length;
654 
655 	while (c != d) {
656 
657 		/* Build time packet */
658 		switch (up->rpt_status) {
659 
660 		    case TSIP_PARSED_DLE_1:
661 			switch (*c)
662 			{
663 			    case 0:
664 			    case DLE:
665 			    case ETX:
666 				up->rpt_status = TSIP_PARSED_EMPTY;
667 				break;
668 
669 			    default:
670 				up->rpt_status = TSIP_PARSED_DATA;
671 				/* save packet ID */
672 				up->rpt_buf[0] = *c;
673 				break;
674 			}
675 			break;
676 
677 		    case TSIP_PARSED_DATA:
678 			if (*c == DLE)
679 			    up->rpt_status = TSIP_PARSED_DLE_2;
680 			else
681 			    mb(up->rpt_cnt++) = *c;
682 			break;
683 
684 		    case TSIP_PARSED_DLE_2:
685 			if (*c == DLE) {
686 				up->rpt_status = TSIP_PARSED_DATA;
687 				mb(up->rpt_cnt++) =
688 						*c;
689 			}
690 			else if (*c == ETX)
691 				    up->rpt_status = TSIP_PARSED_FULL;
692 			else 	{
693                         	/* error: start new report packet */
694 				up->rpt_status = TSIP_PARSED_DLE_1;
695 				up->rpt_buf[0] = *c;
696 			}
697 			break;
698 
699 		    case TSIP_PARSED_FULL:
700 		    case TSIP_PARSED_EMPTY:
701 		    default:
702 		        if ( *c != DLE)
703                           up->rpt_status = TSIP_PARSED_EMPTY;
704                 else
705                           up->rpt_status = TSIP_PARSED_DLE_1;
706                         break;
707 		}
708 
709 		c++;
710 
711 		if (up->rpt_status == TSIP_PARSED_DLE_1) {
712 		    up->rpt_cnt = 0;
713 			if (pp->sloppyclockflag & CLK_FLAG2)
714                 		/* stamp it */
715                        	get_systime(&pp->lastrec);
716 		}
717 		else if (up->rpt_status == TSIP_PARSED_EMPTY)
718 		    	up->rpt_cnt = 0;
719 
720 		else if (up->rpt_cnt > BMAX)
721 			up->rpt_status =TSIP_PARSED_EMPTY;
722 
723 		if (up->rpt_status == TSIP_PARSED_FULL)
724 			palisade_receive(peer);
725 
726 	} /* while chars in buffer */
727 }
728 
729 
730 /*
731  * Trigger the Palisade's event input, which is driven off the RTS
732  *
733  * Take a system time stamp to match the GPS time stamp.
734  *
735  */
736 long
737 HW_poll (
738 #ifdef PALISADE
739 	pp 	/* pointer to unit structure */
740 	)
741 	struct refclockproc * pp;	/* pointer to unit structure */
742 #else
743 	struct refclockproc * pp 	/* pointer to unit structure */
744 	)
745 #endif
746 {
747 	int x;	/* state before & after RTS set */
748 	struct palisade_unit *up;
749 
750 	up = (struct palisade_unit *) pp->unitptr;
751 
752 	/* read the current status, so we put things back right */
753 	if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
754 #ifdef DEBUG
755 	if (debug)
756 	    printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
757 #endif
758 		msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
759 			up->unit);
760 		return -1;
761 	}
762 
763 	x |= TIOCM_RTS;        /* turn on RTS  */
764 
765 	/* Edge trigger */
766 	if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
767 #ifdef DEBUG
768 	if (debug)
769 	    printf("Palisade HW_poll: unit %d: SET \n", up->unit);
770 #endif
771 		msyslog(LOG_ERR,
772 			"Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
773 			up->unit);
774 		return -1;
775 	}
776 
777 	x &= ~TIOCM_RTS;        /* turn off RTS  */
778 
779 	/* poll timestamp */
780 	get_systime(&pp->lastrec);
781 
782 	if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
783 #ifdef DEBUG
784 	if (debug)
785 	    printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
786 #endif
787 		msyslog(LOG_ERR,
788 			"Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
789 			up->unit);
790 		return -1;
791 	}
792 
793 	return 0;
794 }
795 
796 #if 0 /* unused */
797 /*
798  * this 'casts' a character array into a float
799  */
800 float
801 getfloat (
802 #ifdef PALISADE
803 	bp
804 	)
805 	u_char *bp;
806 #else
807 	u_char *bp
808 	)
809 #endif
810 {
811 	float sval;
812 #ifdef WORDS_BIGENDIAN
813 	((char *) &sval)[0] = *bp++;
814 	((char *) &sval)[1] = *bp++;
815 	((char *) &sval)[2] = *bp++;
816 	((char *) &sval)[3] = *bp++;
817 #else
818 	((char *) &sval)[3] = *bp++;
819 	((char *) &sval)[2] = *bp++;
820 	((char *) &sval)[1] = *bp++;
821 	((char *) &sval)[0] = *bp;
822 #endif  /* ! XNTP_BIG_ENDIAN */
823 	return sval;
824 }
825 #endif
826 
827 /*
828  * this 'casts' a character array into a double
829  */
830 double
831 getdbl (
832 #ifdef PALISADE
833 	bp
834 	)
835 	u_char *bp;
836 #else
837 	u_char *bp
838 	)
839 #endif
840 {
841 	double dval;
842 #ifdef WORDS_BIGENDIAN
843 	((char *) &dval)[0] = *bp++;
844 	((char *) &dval)[1] = *bp++;
845 	((char *) &dval)[2] = *bp++;
846 	((char *) &dval)[3] = *bp++;
847 	((char *) &dval)[4] = *bp++;
848 	((char *) &dval)[5] = *bp++;
849 	((char *) &dval)[6] = *bp++;
850 	((char *) &dval)[7] = *bp;
851 #else
852 	((char *) &dval)[7] = *bp++;
853 	((char *) &dval)[6] = *bp++;
854 	((char *) &dval)[5] = *bp++;
855 	((char *) &dval)[4] = *bp++;
856 	((char *) &dval)[3] = *bp++;
857 	((char *) &dval)[2] = *bp++;
858 	((char *) &dval)[1] = *bp++;
859 	((char *) &dval)[0] = *bp;
860 #endif  /* ! XNTP_BIG_ENDIAN */
861 	return dval;
862 }
863 
864 /*
865  * cast a 16 bit character array into a short (16 bit) int
866  */
867 short
868 getint (
869 #ifdef PALISADE
870 	bp
871 	)
872 	u_char *bp;
873 #else
874 	u_char *bp
875 	)
876 #endif
877 {
878 return (short) (bp[1] + (bp[0] << 8));
879 }
880 
881 #endif /* REFCLOCK */
882