refclock_palisade.c revision 56746
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 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 */
63const int days_of_year [12] = {
64	0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
65};
66
67#ifdef DEBUG
68const 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 */
79struct 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
89int day_of_year P((char *dt));
90
91/*
92 * palisade_start - open the devices and initialize data for processing
93 */
94static int
95palisade_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 */
236static void
237palisade_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 */
262int
263day_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 */
295int
296TSIP_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
358if (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)
477printf("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
505static void
506palisade_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 */
588static void
589palisade_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
628static void
629palisade_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 */
736long
737HW_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 */
800float
801getfloat (
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 */
830double
831getdbl (
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 */
867short
868getint (
869#ifdef PALISADE
870	bp
871	)
872	u_char *bp;
873#else
874	u_char *bp
875	)
876#endif
877{
878return (short) (bp[1] + (bp[0] << 8));
879}
880
881#endif /* REFCLOCK */
882