refclock_palisade.c revision 132452
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(SYS_WINNT)
60#undef close
61#define close closesocket
62#endif
63
64#if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
65
66#include "refclock_palisade.h"
67/* Table to get from month to day of the year */
68const int days_of_year [12] = {
69	0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
70};
71
72#ifdef DEBUG
73const char * Tracking_Status[15][15] = {
74        	{ "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
75        	{"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
76        	{ "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
77        	{ "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
78        	{ "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
79#endif
80
81/*
82 * Transfer vector
83 */
84struct refclock refclock_palisade = {
85	palisade_start,		/* start up driver */
86	palisade_shutdown,	/* shut down driver */
87	palisade_poll,		/* transmit poll message */
88	noentry,		/* not used  */
89	noentry,		/* initialize driver (not used) */
90	noentry,		/* not used */
91	NOFLAGS			/* not used */
92};
93
94int day_of_year P((char *dt));
95
96/* Extract the clock type from the mode setting */
97#define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
98
99/* Supported clock types */
100#define CLK_TRIMBLE	0	/* Trimble Palisade */
101#define CLK_PRAECIS	1	/* Endrun Technologies Praecis */
102
103int praecis_msg;
104static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
105
106/*
107 * palisade_start - open the devices and initialize data for processing
108 */
109static int
110palisade_start (
111#ifdef PALISADE
112	unit, peer
113	)
114	int unit;
115	struct peer *peer;
116#else /* ANSI */
117	int unit,
118	struct peer *peer
119	)
120#endif
121{
122	struct palisade_unit *up;
123	struct refclockproc *pp;
124	int fd;
125	char gpsdev[20];
126
127	struct termios tio;
128#ifdef SYS_WINNT
129	(void) sprintf(gpsdev, "COM%d:", unit);
130#else
131	(void) sprintf(gpsdev, DEVICE, unit);
132#endif
133	/*
134	 * Open serial port.
135	 */
136#if defined PALISADE
137	 fd = open(gpsdev, O_RDWR
138#ifdef O_NONBLOCK
139                  | O_NONBLOCK
140#endif
141                  );
142#else /* NTP 4.x */
143	fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
144#endif
145	if (fd <= 0) {
146#ifdef DEBUG
147		printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
148#endif
149		return 0;
150	}
151
152	msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
153		gpsdev);
154
155#if defined PALISADE
156        tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
157        tio.c_iflag = (IGNBRK);
158        tio.c_oflag = (0);
159        tio.c_lflag = (0);
160
161        if (cfsetispeed(&tio, SPEED232) == -1) {
162                msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
163#ifdef DEBUG
164                printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
165#endif
166                return 0;
167        }
168        if (cfsetospeed(&tio, SPEED232) == -1) {
169#ifdef DEBUG
170                printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
171#endif
172                msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
173                return 0;
174        }
175#else /* NTP 4.x */
176        if (tcgetattr(fd, &tio) < 0) {
177                msyslog(LOG_ERR,
178			"Palisade(%d) tcgetattr(fd, &tio): %m",unit);
179#ifdef DEBUG
180                printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
181#endif
182                return (0);
183        }
184
185        tio.c_cflag |= (PARENB|PARODD);
186        tio.c_iflag &= ~ICRNL;
187#endif /*  NTP 4.x */
188
189	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
190                msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
191#ifdef DEBUG
192                printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
193#endif
194                return 0;
195        }
196
197	/*
198	 * Allocate and initialize unit structure
199	 */
200	up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
201
202	if (!(up)) {
203                msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
204#ifdef DEBUG
205                printf("Palisade(%d) emalloc\n",unit);
206#endif
207		(void) close(fd);
208		return (0);
209	}
210
211	memset((char *)up, 0, sizeof(struct palisade_unit));
212
213	up->type = CLK_TYPE(peer);
214	switch (up->type) {
215		case CLK_TRIMBLE:
216			/* Normal mode, do nothing */
217			break;
218		case CLK_PRAECIS:
219			msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled\n",unit);
220			break;
221		default:
222			msyslog(LOG_NOTICE, "Palisade(%d) mode unknown\n",unit);
223			break;
224	}
225
226	pp = peer->procptr;
227	pp->io.clock_recv = palisade_io;
228	pp->io.srcclock = (caddr_t)peer;
229	pp->io.datalen = 0;
230	pp->io.fd = fd;
231	if (!io_addclock(&pp->io)) {
232#ifdef DEBUG
233                printf("Palisade(%d) io_addclock\n",unit);
234#endif
235		(void) close(fd);
236		free(up);
237		return (0);
238	}
239
240	/*
241	 * Initialize miscellaneous variables
242	 */
243	pp->unitptr = (caddr_t)up;
244	pp->clockdesc = DESCRIPTION;
245
246	peer->precision = PRECISION;
247	peer->sstclktype = CTL_SST_TS_UHF;
248	peer->minpoll = TRMB_MINPOLL;
249	peer->maxpoll = TRMB_MAXPOLL;
250	memcpy((char *)&pp->refid, REFID, 4);
251
252	up->leap_status = 0;
253	up->unit = (short) unit;
254	up->rpt_status = TSIP_PARSED_EMPTY;
255    	up->rpt_cnt = 0;
256
257	return 1;
258}
259
260
261/*
262 * palisade_shutdown - shut down the clock
263 */
264static void
265palisade_shutdown (
266#ifdef PALISADE
267	unit, peer
268	)
269	int unit;
270	struct peer *peer;
271#else /* ANSI */
272	int unit,
273	struct peer *peer
274	)
275#endif
276{
277	struct palisade_unit *up;
278	struct refclockproc *pp;
279	pp = peer->procptr;
280	up = (struct palisade_unit *)pp->unitptr;
281	io_closeclock(&pp->io);
282	free(up);
283}
284
285
286
287/*
288 * unpack_date - get day and year from date
289 */
290int
291day_of_year (
292#ifdef PALISADE
293	dt
294	)
295	char * dt;
296#else
297	char * dt
298	)
299#endif
300{
301	int day, mon, year;
302
303	mon = dt[1];
304       /* Check month is inside array bounds */
305       if ((mon < 1) || (mon > 12))
306		return -1;
307
308	day = dt[0] + days_of_year[mon - 1];
309	year = getint((u_char *) (dt + 2));
310
311	if ( !(year % 4) && ((year % 100) ||
312		(!(year % 100) && !(year%400)))
313			&&(mon > 2))
314			day ++; /* leap year and March or later */
315
316	return day;
317}
318
319
320/*
321 * TSIP_decode - decode the TSIP data packets
322 */
323int
324TSIP_decode (
325#ifdef PALISADE
326	peer
327	)
328	struct peer *peer;
329#else
330	struct peer *peer
331	)
332#endif
333{
334	int st;
335	long   secint;
336	double secs;
337	double secfrac;
338	unsigned short event = 0;
339
340	struct palisade_unit *up;
341	struct refclockproc *pp;
342
343	pp = peer->procptr;
344	up = (struct palisade_unit *)pp->unitptr;
345
346	/*
347	 * Check the time packet, decode its contents.
348	 * If the timecode has invalid length or is not in
349	 * proper format, declare bad format and exit.
350	 */
351
352	if ((up->rpt_buf[0] == (char) 0x41) ||
353		(up->rpt_buf[0] == (char) 0x46) ||
354		(up->rpt_buf[0] == (char) 0x54) ||
355		(up->rpt_buf[0] == (char) 0x4B) ||
356		(up->rpt_buf[0] == (char) 0x6D)) {
357
358	/* standard time packet - GPS time and GPS week number */
359#ifdef DEBUG
360			printf("Palisade Port B packets detected. Connect to Port A\n");
361#endif
362
363		return 0;
364	}
365
366	/*
367	 * We cast both to u_char to as 0x8f uses the sign bit on a char
368	 */
369	if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
370	/*
371	 * Superpackets
372	 */
373	   event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
374	   if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
375		/* Ignore Packet */
376			return 0;
377
378	   switch (mb(0) & 0xff) {
379	     int GPS_UTC_Offset;
380	     case PACKET_8F0B:
381
382		if (up->polled <= 0)
383			return 0;
384
385		if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
386			break;
387
388#ifdef DEBUG
389if (debug > 1) {
390		int ts;
391		double lat, lon, alt;
392		lat = getdbl((u_char *) &mb(42)) * R2D;
393		lon = getdbl((u_char *) &mb(50)) * R2D;
394		alt = getdbl((u_char *) &mb(58));
395
396  		printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
397				up->unit, lat,lon,alt);
398  		printf("TSIP_decode: unit %d: Sats:", up->unit);
399		for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
400			if (mb(st) > 0) ts++;
401			printf(" %02d", mb(st));
402		}
403		printf(" : Tracking %d\n", ts);
404	}
405#endif
406
407		GPS_UTC_Offset = getint((u_char *) &mb(16));
408		if (GPS_UTC_Offset == 0) { /* Check UTC offset */
409#ifdef DEBUG
410			 printf("TSIP_decode: UTC Offset Unknown\n");
411#endif
412			break;
413		}
414
415		secs = getdbl((u_char *) &mb(3));
416		secint = (long) secs;
417		secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
418
419		pp->nsec = (long) (secfrac * 1000000000);
420
421		secint %= 86400;    /* Only care about today */
422		pp->hour = secint / 3600;
423		secint %= 3600;
424		pp->minute = secint / 60;
425		secint %= 60;
426		pp->second = secint % 60;
427
428		if ((pp->day = day_of_year(&mb(11))) < 0) break;
429
430		pp->year = getint((u_char *) &mb(13));
431
432#ifdef DEBUG
433	if (debug > 1)
434		printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
435 			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
436			pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
437#endif
438		/* Only use this packet when no
439		 * 8F-AD's are being received
440		 */
441
442		if (up->leap_status) {
443			up->leap_status = 0;
444			return 0;
445		}
446
447		return 2;
448		break;
449
450	  case PACKET_NTP:
451		/* Palisade-NTP Packet */
452
453		if (up->rpt_cnt != LENCODE_NTP) /* check length */
454			break;
455
456		up->leap_status = mb(19);
457
458		if (up->polled  <= 0)
459			return 0;
460
461		/* Check Tracking Status */
462		st = mb(18);
463		if (st < 0 || st > 14) st = 14;
464		if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
465#ifdef DEBUG
466		 printf("TSIP_decode: Not Tracking Sats : %s\n",
467				*Tracking_Status[st]);
468#endif
469			refclock_report(peer, CEVNT_BADTIME);
470			up->polled = -1;
471			return 0;
472			break;
473		}
474
475		if (up->leap_status & PALISADE_LEAP_PENDING) {
476			if (up->leap_status & PALISADE_UTC_TIME)
477				pp->leap = LEAP_ADDSECOND;
478			else
479				pp->leap = LEAP_DELSECOND;
480		}
481		else if (up->leap_status)
482			pp->leap = LEAP_NOWARNING;
483
484		else {  /* UTC flag is not set:
485			 * Receiver may have been reset, and lost
486			 * its UTC almanac data */
487			pp->leap = LEAP_NOTINSYNC;
488#ifdef DEBUG
489			 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
490				mb(19));
491#endif
492			refclock_report(peer, CEVNT_BADTIME);
493			up->polled = -1;
494			return 0;
495		}
496
497		pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
498
499		if ((pp->day = day_of_year(&mb(14))) < 0)
500			break;
501		pp->year = getint((u_char *) &mb(16));
502		pp->hour = mb(11);
503		pp->minute = mb(12);
504		pp->second = mb(13);
505
506#ifdef DEBUG
507	if (debug > 1)
508printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
509 			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
510			pp->second, pp->nsec, mb(15), mb(14), pp->year,
511			mb(19), *Tracking_Status[st]);
512#endif
513		return 1;
514		break;
515
516	  default:
517		/* Ignore Packet */
518		return 0;
519	  } /* switch */
520	}/* if 8F packets */
521
522	refclock_report(peer, CEVNT_BADREPLY);
523	up->polled = -1;
524#ifdef DEBUG
525	printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
526		   up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
527			event, up->rpt_cnt);
528#endif
529	return 0;
530}
531
532/*
533 * palisade__receive - receive data from the serial interface
534 */
535
536static void
537palisade_receive (
538#ifdef PALISADE
539	peer
540	)
541	struct peer * peer;
542#else /* ANSI */
543	struct peer * peer
544	)
545#endif
546{
547	struct palisade_unit *up;
548	struct refclockproc *pp;
549
550	/*
551	 * Initialize pointers and read the timecode and timestamp.
552	 */
553	pp = peer->procptr;
554	up = (struct palisade_unit *)pp->unitptr;
555
556	if (! TSIP_decode(peer)) return;
557
558	if (up->polled <= 0)
559	    return;   /* no poll pending, already received or timeout */
560
561	up->polled = 0;  /* Poll reply received */
562	pp->lencode = 0; /* clear time code */
563#ifdef DEBUG
564	if (debug)
565		printf(
566	"palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
567			up->unit, pp->year, pp->day, pp->hour, pp->minute,
568			pp->second, pp->nsec);
569#endif
570
571	/*
572	 * Process the sample
573	 * Generate timecode: YYYY DoY HH:MM:SS.microsec
574	 * report and process
575	 */
576
577	(void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
578		   pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->nsec);
579	pp->lencode = 24;
580
581#ifdef PALISADE
582    	pp->lasttime = current_time;
583#endif
584	if (!refclock_process(pp
585#ifdef PALISADE
586		, PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
587#endif
588		)) {
589		refclock_report(peer, CEVNT_BADTIME);
590
591#ifdef DEBUG
592		printf("palisade_receive: unit %d: refclock_process failed!\n",
593			up->unit);
594#endif
595		return;
596	}
597
598	record_clock_stats(&peer->srcadr, pp->a_lastcode);
599
600#ifdef DEBUG
601	if (debug)
602	    printf("palisade_receive: unit %d: %s\n",
603		   up->unit, prettydate(&pp->lastrec));
604#endif
605	pp->lastref = pp->lastrec;
606	refclock_receive(peer
607#ifdef PALISADE
608		, &pp->offset, 0, pp->dispersion,
609              &pp->lastrec, &pp->lastrec, pp->leap
610#endif
611		);
612}
613
614
615/*
616 * palisade_poll - called by the transmit procedure
617 *
618 */
619static void
620palisade_poll (
621#ifdef PALISADE
622	unit, peer
623	)
624	int unit;
625	struct peer *peer;
626#else
627	int unit,
628	struct peer *peer
629	)
630#endif
631{
632	struct palisade_unit *up;
633	struct refclockproc *pp;
634
635	pp = peer->procptr;
636	up = (struct palisade_unit *)pp->unitptr;
637
638	pp->polls++;
639	if (up->polled > 0) /* last reply never arrived or error */
640	    refclock_report(peer, CEVNT_TIMEOUT);
641
642	up->polled = 2; /* synchronous packet + 1 event */
643
644#ifdef DEBUG
645	if (debug)
646	    printf("palisade_poll: unit %d: polling %s\n", unit,
647		   (pp->sloppyclockflag & CLK_FLAG2) ?
648			"synchronous packet" : "event");
649#endif
650
651	if (pp->sloppyclockflag & CLK_FLAG2)
652	    return;  /* using synchronous packet input */
653
654	if(up->type == CLK_PRAECIS) {
655		if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
656			msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
657		else {
658			praecis_msg = 1;
659			return;
660		}
661	}
662
663	if (HW_poll(pp) < 0)
664	    refclock_report(peer, CEVNT_FAULT);
665}
666
667static void
668praecis_parse(struct recvbuf *rbufp, struct peer *peer)
669{
670	static char buf[100];
671	static int p = 0;
672	struct refclockproc *pp;
673
674	pp = peer->procptr;
675
676	memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
677	p += rbufp->recv_length;
678
679	if(buf[p-2] == '\r' && buf[p-1] == '\n') {
680		buf[p-2] = '\0';
681		record_clock_stats(&peer->srcadr, buf);
682
683		p = 0;
684		praecis_msg = 0;
685
686		if (HW_poll(pp) < 0)
687			refclock_report(peer, CEVNT_FAULT);
688
689	}
690}
691
692static void
693palisade_io (
694#ifdef PALISADE
695	rbufp
696	)
697	struct recvbuf *rbufp;
698#else /* ANSI */
699	struct recvbuf *rbufp
700	)
701#endif
702{
703	/*
704	 * Initialize pointers and read the timecode and timestamp.
705	 */
706	struct palisade_unit *up;
707	struct refclockproc *pp;
708	struct peer *peer;
709
710	char * c, * d;
711
712	peer = (struct peer *)rbufp->recv_srcclock;
713	pp = peer->procptr;
714	up = (struct palisade_unit *)pp->unitptr;
715
716	if(up->type == CLK_PRAECIS) {
717		if(praecis_msg) {
718			praecis_parse(rbufp,peer);
719			return;
720		}
721	}
722
723	c = (char *) &rbufp->recv_space;
724	d = c + rbufp->recv_length;
725
726	while (c != d) {
727
728		/* Build time packet */
729		switch (up->rpt_status) {
730
731		    case TSIP_PARSED_DLE_1:
732			switch (*c)
733			{
734			    case 0:
735			    case DLE:
736			    case ETX:
737				up->rpt_status = TSIP_PARSED_EMPTY;
738				break;
739
740			    default:
741				up->rpt_status = TSIP_PARSED_DATA;
742				/* save packet ID */
743				up->rpt_buf[0] = *c;
744				break;
745			}
746			break;
747
748		    case TSIP_PARSED_DATA:
749			if (*c == DLE)
750			    up->rpt_status = TSIP_PARSED_DLE_2;
751			else
752			    mb(up->rpt_cnt++) = *c;
753			break;
754
755		    case TSIP_PARSED_DLE_2:
756			if (*c == DLE) {
757				up->rpt_status = TSIP_PARSED_DATA;
758				mb(up->rpt_cnt++) =
759						*c;
760			}
761			else if (*c == ETX)
762				    up->rpt_status = TSIP_PARSED_FULL;
763			else 	{
764                        	/* error: start new report packet */
765				up->rpt_status = TSIP_PARSED_DLE_1;
766				up->rpt_buf[0] = *c;
767			}
768			break;
769
770		    case TSIP_PARSED_FULL:
771		    case TSIP_PARSED_EMPTY:
772		    default:
773		        if ( *c != DLE)
774                          up->rpt_status = TSIP_PARSED_EMPTY;
775                else
776                          up->rpt_status = TSIP_PARSED_DLE_1;
777                        break;
778		}
779
780		c++;
781
782		if (up->rpt_status == TSIP_PARSED_DLE_1) {
783		    up->rpt_cnt = 0;
784			if (pp->sloppyclockflag & CLK_FLAG2)
785                		/* stamp it */
786                       	get_systime(&pp->lastrec);
787		}
788		else if (up->rpt_status == TSIP_PARSED_EMPTY)
789		    	up->rpt_cnt = 0;
790
791		else if (up->rpt_cnt > BMAX)
792			up->rpt_status =TSIP_PARSED_EMPTY;
793
794		if (up->rpt_status == TSIP_PARSED_FULL)
795			palisade_receive(peer);
796
797	} /* while chars in buffer */
798}
799
800
801/*
802 * Trigger the Palisade's event input, which is driven off the RTS
803 *
804 * Take a system time stamp to match the GPS time stamp.
805 *
806 */
807long
808HW_poll (
809#ifdef PALISADE
810	pp 	/* pointer to unit structure */
811	)
812	struct refclockproc * pp;	/* pointer to unit structure */
813#else
814	struct refclockproc * pp 	/* pointer to unit structure */
815	)
816#endif
817{
818	int x;	/* state before & after RTS set */
819	struct palisade_unit *up;
820
821	up = (struct palisade_unit *) pp->unitptr;
822
823	/* read the current status, so we put things back right */
824	if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
825#ifdef DEBUG
826	if (debug)
827	    printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
828#endif
829		msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
830			up->unit);
831		return -1;
832	}
833
834	x |= TIOCM_RTS;        /* turn on RTS  */
835
836	/* Edge trigger */
837	if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
838#ifdef DEBUG
839	if (debug)
840	    printf("Palisade HW_poll: unit %d: SET \n", up->unit);
841#endif
842		msyslog(LOG_ERR,
843			"Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
844			up->unit);
845		return -1;
846	}
847
848	x &= ~TIOCM_RTS;        /* turn off RTS  */
849
850	/* poll timestamp */
851	get_systime(&pp->lastrec);
852
853	if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
854#ifdef DEBUG
855	if (debug)
856	    printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
857#endif
858		msyslog(LOG_ERR,
859			"Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
860			up->unit);
861		return -1;
862	}
863
864	return 0;
865}
866
867#if 0 /* unused */
868/*
869 * this 'casts' a character array into a float
870 */
871float
872getfloat (
873#ifdef PALISADE
874	bp
875	)
876	u_char *bp;
877#else
878	u_char *bp
879	)
880#endif
881{
882	float sval;
883#ifdef WORDS_BIGENDIAN
884	((char *) &sval)[0] = *bp++;
885	((char *) &sval)[1] = *bp++;
886	((char *) &sval)[2] = *bp++;
887	((char *) &sval)[3] = *bp++;
888#else
889	((char *) &sval)[3] = *bp++;
890	((char *) &sval)[2] = *bp++;
891	((char *) &sval)[1] = *bp++;
892	((char *) &sval)[0] = *bp;
893#endif  /* ! XNTP_BIG_ENDIAN */
894	return sval;
895}
896#endif
897
898/*
899 * this 'casts' a character array into a double
900 */
901double
902getdbl (
903#ifdef PALISADE
904	bp
905	)
906	u_char *bp;
907#else
908	u_char *bp
909	)
910#endif
911{
912	double dval;
913#ifdef WORDS_BIGENDIAN
914	((char *) &dval)[0] = *bp++;
915	((char *) &dval)[1] = *bp++;
916	((char *) &dval)[2] = *bp++;
917	((char *) &dval)[3] = *bp++;
918	((char *) &dval)[4] = *bp++;
919	((char *) &dval)[5] = *bp++;
920	((char *) &dval)[6] = *bp++;
921	((char *) &dval)[7] = *bp;
922#else
923	((char *) &dval)[7] = *bp++;
924	((char *) &dval)[6] = *bp++;
925	((char *) &dval)[5] = *bp++;
926	((char *) &dval)[4] = *bp++;
927	((char *) &dval)[3] = *bp++;
928	((char *) &dval)[2] = *bp++;
929	((char *) &dval)[1] = *bp++;
930	((char *) &dval)[0] = *bp;
931#endif  /* ! XNTP_BIG_ENDIAN */
932	return dval;
933}
934
935/*
936 * cast a 16 bit character array into a short (16 bit) int
937 */
938short
939getint (
940#ifdef PALISADE
941	bp
942	)
943	u_char *bp;
944#else
945	u_char *bp
946	)
947#endif
948{
949return (short) (bp[1] + (bp[0] << 8));
950}
951
952#else
953int refclock_palisade_bs;
954#endif /* REFCLOCK */
955