]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/refclock_palisade.c
MFC r362568:
[FreeBSD/FreeBSD.git] / contrib / ntp / ntpd / refclock_palisade.c
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  * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
56  *           Contact: Fernando Pablo Hauscarriaga
57  *           E-mail: fernandoph@iar.unlp.edu.ar
58  *           Home page: www.iar.unlp.edu.ar/~fernandoph
59  *                Instituto Argentino de Radioastronomia
60  *                          www.iar.unlp.edu.ar
61  *
62  * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
63  *           now we use mode 2 for decode thunderbolt packets.
64  *           Fernando P. Hauscarriaga
65  *
66  * 30/08/09: Added support for Trimble Acutime Gold Receiver.
67  *           Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
68  *
69  * 21/04/18: Added support for Resolution devices.
70  *
71  * 03/09/19: Added support for ACE III & Copernicus II.
72  */
73
74 #ifdef HAVE_CONFIG_H
75 # include "config.h"
76 #endif
77
78 #if defined(REFCLOCK) && defined(CLOCK_PALISADE)
79
80 #ifdef SYS_WINNT
81 extern int async_write(int, const void *, unsigned int);
82 #undef write
83 #define write(fd, data, octets) async_write(fd, data, octets)
84 #endif
85
86 #include "refclock_palisade.h"
87
88 #ifdef DEBUG
89 const char * Tracking_Status[15][15] = { 
90         { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
91         {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
92         { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
93         { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
94         { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
95 #endif
96
97 /*
98  * Transfer vector
99  */
100 struct refclock refclock_palisade = {
101         palisade_start,         /* start up driver */
102         palisade_shutdown,      /* shut down driver */
103         palisade_poll,          /* transmit poll message */
104         noentry,                /* not used  */
105         noentry,                /* initialize driver (not used) */
106         noentry,                /* not used */
107         NOFLAGS                 /* not used */
108 };
109
110 static int decode_date(struct refclockproc *pp, const char *cp);
111
112 /* Extract the clock type from the mode setting */
113 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
114
115 /* Supported clock types */
116 #define CLK_TRIMBLE     0       /* Trimble Palisade */
117 #define CLK_PRAECIS     1       /* Endrun Technologies Praecis */
118 #define CLK_THUNDERBOLT 2       /* Trimble Thunderbolt GPS Receiver */
119 #define CLK_ACUTIME     3       /* Trimble Acutime Gold */
120 #define CLK_ACUTIMEB    4       /* Trimble Actutime Gold Port B */
121 #define CLK_RESOLUTION  5       /* Trimble Resolution Receivers */
122 #define CLK_ACE         6       /* Trimble ACE III */
123 #define CLK_COPERNICUS  7       /* Trimble Copernicus II */
124
125 int praecis_msg;
126 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
127
128 /* These routines are for sending packets to the Thunderbolt receiver
129  * They are taken from Markus Prosch
130  */
131
132 /*
133  * sendcmd - Build data packet for sending
134  */
135 static void 
136 sendcmd (
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  */
149 static void 
150 sendsupercmd (
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  */
165 static void 
166 sendbyte (
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  */
179 static void 
180 sendint (
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  */
192 static int 
193 sendetx (
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  */
214 static void
215 init_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  */
240 static void
241 init_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  */
265 static void
266 init_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  */
296 static int
297 palisade_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(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  */
441 static void
442 palisade_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
462 static inline uint8_t
463 get_u8(
464         const char *cp)
465 {
466         return ((const u_char*)cp)[0];
467 }
468
469 static inline uint16_t
470 get_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  */
482 int
483 decode_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  */
534 int
535 TSIP_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
1132 static void
1133 palisade_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  */
1199 static void
1200 palisade_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
1240 static void
1241 praecis_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         memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
1253         p += rbufp->recv_length;
1254
1255         if(buf[p-2] == '\r' && buf[p-1] == '\n') {
1256                 buf[p-2] = '\0';
1257                 record_clock_stats(&peer->srcadr, buf);
1258
1259                 p = 0;
1260                 praecis_msg = 0;
1261
1262                 if (HW_poll(pp) < 0)
1263                         refclock_report(peer, CEVNT_FAULT);
1264
1265         }
1266 }
1267
1268 static void
1269 palisade_io (
1270         struct recvbuf *rbufp
1271         )
1272 {
1273         /*
1274          * Initialize pointers and read the timecode and timestamp.
1275          */
1276         struct palisade_unit *up;
1277         struct refclockproc *pp;
1278         struct peer *peer;
1279
1280         char * c, * d;
1281
1282         peer = rbufp->recv_peer;
1283         pp = peer->procptr;
1284         up = pp->unitptr;
1285
1286         if(up->type == CLK_PRAECIS) {
1287                 if(praecis_msg) {
1288                         praecis_parse(rbufp,peer);
1289                         return;
1290                 }
1291         }
1292
1293         c = (char *) &rbufp->recv_space;
1294         d = c + rbufp->recv_length;
1295                 
1296         while (c != d) {
1297
1298                 /* Build time packet */
1299                 switch (up->rpt_status) {
1300
1301                     case TSIP_PARSED_DLE_1:
1302                         switch (*c)
1303                         {
1304                             case 0:
1305                             case DLE:
1306                             case ETX:
1307                                 up->rpt_status = TSIP_PARSED_EMPTY;
1308                                 break;
1309
1310                             default:
1311                                 up->rpt_status = TSIP_PARSED_DATA;
1312                                 /* save packet ID */
1313                                 up->rpt_buf[0] = *c;
1314                                 break;
1315                         }
1316                         break;
1317
1318                     case TSIP_PARSED_DATA:
1319                         if (*c == DLE)
1320                                 up->rpt_status = TSIP_PARSED_DLE_2;
1321                         else 
1322                                 mb(up->rpt_cnt++) = *c;
1323                         break;
1324
1325                     case TSIP_PARSED_DLE_2:
1326                         if (*c == DLE) {
1327                                 up->rpt_status = TSIP_PARSED_DATA;
1328                                 mb(up->rpt_cnt++) = 
1329                                     *c;
1330                         }
1331                         else if (*c == ETX) 
1332                                 up->rpt_status = TSIP_PARSED_FULL;
1333                         else    {
1334                                 /* error: start new report packet */
1335                                 up->rpt_status = TSIP_PARSED_DLE_1;
1336                                 up->rpt_buf[0] = *c;
1337                         }
1338                         break;
1339
1340                     case TSIP_PARSED_FULL:
1341                     case TSIP_PARSED_EMPTY:
1342                     default:
1343                         if ( *c != DLE)
1344                                 up->rpt_status = TSIP_PARSED_EMPTY;
1345                         else 
1346                                 up->rpt_status = TSIP_PARSED_DLE_1;
1347                         break;
1348                 }
1349                 
1350                 c++;
1351
1352                 if (up->rpt_status == TSIP_PARSED_DLE_1) {
1353                         up->rpt_cnt = 0;
1354                         if (pp->sloppyclockflag & CLK_FLAG2) 
1355                                 /* stamp it */
1356                                 get_systime(&pp->lastrec);
1357                 }
1358                 else if (up->rpt_status == TSIP_PARSED_EMPTY)
1359                         up->rpt_cnt = 0;
1360
1361                 else if (up->rpt_cnt > BMAX) 
1362                         up->rpt_status =TSIP_PARSED_EMPTY;
1363
1364                 if (up->rpt_status == TSIP_PARSED_FULL) 
1365                         palisade_receive(peer);
1366
1367         } /* while chars in buffer */
1368 }
1369
1370
1371 /*
1372  * Trigger the Palisade's event input, which is driven off the RTS
1373  *
1374  * Take a system time stamp to match the GPS time stamp.
1375  *
1376  */
1377 long
1378 HW_poll (
1379         struct refclockproc * pp        /* pointer to unit structure */
1380         )
1381 {       
1382         int x;  /* state before & after RTS set */
1383         struct palisade_unit *up;
1384         struct packettx tx;
1385
1386         up = pp->unitptr;
1387
1388         if (up->type == CLK_ACE) {
1389                 /* Poll by sending a 0x21 command */
1390                 tx.size = 0;
1391                 tx.data = (u_char *) emalloc(100);
1392                 sendcmd (&tx, 0x21);
1393                 sendetx (&tx, pp->io.fd);
1394                 free(tx.data);
1395         } else {
1396
1397         /* read the current status, so we put things back right */
1398         if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1399                 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1400                         up->unit));
1401                 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 
1402                         up->unit);
1403                 return -1;
1404         }
1405   
1406         x |= TIOCM_RTS;        /* turn on RTS  */
1407
1408         /* Edge trigger */
1409         if (up->type == CLK_ACUTIME)
1410                 write (pp->io.fd, "", 1);
1411                 
1412         if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 
1413 #ifdef DEBUG
1414                 if (debug)
1415                         printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1416 #endif
1417                 msyslog(LOG_ERR,
1418                         "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 
1419                         up->unit);
1420                 return -1;
1421         }
1422
1423         x &= ~TIOCM_RTS;        /* turn off RTS  */
1424         
1425         } /* (up->type != CLK_ACE) */
1426
1427         /* poll timestamp */
1428         get_systime(&pp->lastrec);
1429
1430         if (up->type != CLK_ACE) {
1431         if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1432 #ifdef DEBUG
1433                 if (debug)
1434                         printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1435 #endif
1436                 msyslog(LOG_ERR,
1437                         "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 
1438                         up->unit);
1439                 return -1;
1440         }
1441         }
1442
1443         return 0;
1444 }
1445
1446 /*
1447  * copy/swap a big-endian palisade double into a host double
1448  */
1449 static double
1450 getdbl (
1451         u_char *bp
1452         )
1453 {
1454 #ifdef WORDS_BIGENDIAN
1455         double out;
1456
1457         memcpy(&out, bp, sizeof(out));
1458         return out;
1459 #else
1460         union {
1461                 u_char ch[8];
1462                 u_int32 u32[2];
1463         } ui;
1464                 
1465         union {
1466                 double out;
1467                 u_int32 u32[2];
1468         } uo;
1469
1470         memcpy(ui.ch, bp, sizeof(ui.ch));
1471         /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1472         uo.u32[0] = ntohl(ui.u32[1]);
1473         /* most-significant 32 bits from swapped bp[0] to bp[3] */
1474         uo.u32[1] = ntohl(ui.u32[0]);
1475
1476         return uo.out;
1477 #endif
1478 }
1479
1480 /*
1481  * copy/swap a big-endian palisade short into a host short
1482  */
1483 static short
1484 getint (
1485         u_char *bp
1486         )
1487 {
1488         u_short us;
1489
1490         memcpy(&us, bp, sizeof(us));
1491         return (short)ntohs(us);
1492 }
1493
1494 /*
1495  * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1496  */
1497 static int32
1498 getlong(
1499         u_char *bp
1500         )
1501 {
1502         u_int32 u32;
1503
1504         memcpy(&u32, bp, sizeof(u32));
1505         return (int32)(u_int32)ntohl(u32);
1506 }
1507
1508 /*
1509  * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int
1510  */
1511 static int32
1512 getsingle(
1513         u_char *bp
1514         )
1515 {
1516         u_int32 mantissa;
1517         int8_t exponent;
1518         uint8_t sign, exp_field;
1519         int32 res;
1520
1521         memcpy(&mantissa, bp, sizeof(mantissa));
1522         mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000;
1523         exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7);
1524         exponent = (int8_t)exp_field - 127;
1525         sign = ((uint8_t)bp[0] >> 7);
1526         if (exponent > 23)
1527                 res = (int32)(mantissa << (exponent - 23));
1528         else
1529                 res = (int32)(mantissa >> (23 - exponent));
1530         return sign ? -res : res;
1531 }
1532
1533 #else   /* REFCLOCK && CLOCK_PALISADE*/
1534 int refclock_palisade_c_notempty;
1535 #endif