]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/ntpd/refclock_palisade.c
Upgrade NTP to 4.2.8p4.
[FreeBSD/releng/10.2.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
70 #ifdef HAVE_CONFIG_H
71 # include "config.h"
72 #endif
73
74 #if defined(REFCLOCK) && defined(CLOCK_PALISADE)
75
76 #ifdef SYS_WINNT
77 extern int async_write(int, const void *, unsigned int);
78 #undef write
79 #define write(fd, data, octets) async_write(fd, data, octets)
80 #endif
81
82 #include "refclock_palisade.h"
83 /* Table to get from month to day of the year */
84 const int days_of_year [12] = {
85         0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
86 };
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 int day_of_year (char *dt);
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
122 int praecis_msg;
123 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
124
125 /* These routines are for sending packets to the Thunderbolt receiver
126  * They are taken from Markus Prosch
127  */
128
129 #ifdef PALISADE_SENDCMD_RESURRECTED
130 /*
131  * sendcmd - Build data packet for sending
132  */
133 static void 
134 sendcmd (
135         struct packettx *buffer,
136         int c
137         )
138 {
139         *buffer->data = DLE;
140         *(buffer->data + 1) = (unsigned char)c;
141         buffer->size = 2;
142 }
143 #endif  /* PALISADE_SENDCMD_RESURRECTED */
144
145 /*
146  * sendsupercmd - Build super data packet for sending
147  */
148 static void 
149 sendsupercmd (
150         struct packettx *buffer,
151         int c1,
152         int c2
153         )
154 {
155         *buffer->data = DLE;
156         *(buffer->data + 1) = (unsigned char)c1;
157         *(buffer->data + 2) = (unsigned char)c2;
158         buffer->size = 3;
159 }
160
161 /*
162  * sendbyte -
163  */
164 static void 
165 sendbyte (
166         struct packettx *buffer,
167         int b
168         )
169 {
170         if (b == DLE)
171                 *(buffer->data+buffer->size++) = DLE;
172         *(buffer->data+buffer->size++) = (unsigned char)b;
173 }
174
175 /*
176  * sendint -
177  */
178 static void 
179 sendint (
180         struct packettx *buffer,
181         int a
182         )
183 {
184         sendbyte(buffer, (unsigned char)((a>>8) & 0xff));
185         sendbyte(buffer, (unsigned char)(a & 0xff));
186 }
187
188 /*
189  * sendetx - Send packet or super packet to the device
190  */
191 static int 
192 sendetx (
193         struct packettx *buffer,
194         int fd
195         )
196 {
197         int result;
198         
199         *(buffer->data+buffer->size++) = DLE;
200         *(buffer->data+buffer->size++) = ETX;
201         result = write(fd, buffer->data, (unsigned long)buffer->size);
202         
203         if (result != -1)
204                 return (result);
205         else
206                 return (-1);
207 }
208
209 /*
210  * init_thunderbolt - Prepares Thunderbolt receiver to be used with
211  *                    NTP (also taken from Markus Prosch).
212  */
213 static void
214 init_thunderbolt (
215         int fd
216         )
217 {
218         struct packettx tx;
219         
220         tx.size = 0;
221         tx.data = (u_char *) emalloc(100);
222
223         /* set UTC time */
224         sendsupercmd (&tx, 0x8E, 0xA2);
225         sendbyte     (&tx, 0x3);
226         sendetx      (&tx, fd);
227         
228         /* activate packets 0x8F-AB and 0x8F-AC */
229         sendsupercmd (&tx, 0x8F, 0xA5);
230         sendint      (&tx, 0x5);
231         sendetx      (&tx, fd);
232
233         free(tx.data);
234 }
235
236 /*
237  * init_acutime - Prepares Acutime Receiver to be used with NTP
238  */
239 static void
240 init_acutime (
241         int fd
242         )
243 {
244         /* Disable all outputs, Enable Event-Polling on PortA so
245            we can ask for time packets */
246         struct packettx tx;
247
248         tx.size = 0;
249         tx.data = (u_char *) emalloc(100);
250
251         sendsupercmd(&tx, 0x8E, 0xA5);
252         sendbyte(&tx, 0x02);
253         sendbyte(&tx, 0x00);
254         sendbyte(&tx, 0x00);
255         sendbyte(&tx, 0x00);
256         sendetx(&tx, fd);
257
258         free(tx.data);
259 }
260
261 /*
262  * palisade_start - open the devices and initialize data for processing
263  */
264 static int
265 palisade_start (
266         int unit,
267         struct peer *peer
268         )
269 {
270         struct palisade_unit *up;
271         struct refclockproc *pp;
272         int fd;
273         char gpsdev[20];
274         struct termios tio;
275
276         snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
277
278         /*
279          * Open serial port. 
280          */
281         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
282         if (fd <= 0) {
283 #ifdef DEBUG
284                 printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
285 #endif
286                 return 0;
287         }
288
289         msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
290                 gpsdev);
291
292         if (tcgetattr(fd, &tio) < 0) {
293                 msyslog(LOG_ERR, 
294                         "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
295 #ifdef DEBUG
296                 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
297 #endif
298                 close(fd);
299                 return (0);
300         }
301
302         tio.c_cflag |= (PARENB|PARODD);
303         tio.c_iflag &= ~ICRNL;
304
305         /*
306          * Allocate and initialize unit structure
307          */
308         up = emalloc_zero(sizeof(*up));
309
310         up->type = CLK_TYPE(peer);
311         switch (up->type) {
312             case CLK_TRIMBLE:
313                 /* Normal mode, do nothing */
314                 break;
315             case CLK_PRAECIS:
316                 msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled"
317                         ,unit);
318                 break;
319             case CLK_THUNDERBOLT:
320                 msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled"
321                         ,unit);
322                 tio.c_cflag = (CS8|CLOCAL|CREAD);
323                 break;
324             case CLK_ACUTIME:
325                 msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled"
326                         ,unit);
327                 break;
328             default:
329                 msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit);
330                 break;
331         }
332         if (tcsetattr(fd, TCSANOW, &tio) == -1) {
333                 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
334 #ifdef DEBUG
335                 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
336 #endif
337                 close(fd);
338                 free(up);
339                 return 0;
340         }
341
342         pp = peer->procptr;
343         pp->io.clock_recv = palisade_io;
344         pp->io.srcclock = peer;
345         pp->io.datalen = 0;
346         pp->io.fd = fd;
347         if (!io_addclock(&pp->io)) {
348 #ifdef DEBUG
349                 printf("Palisade(%d) io_addclock\n",unit);
350 #endif
351                 close(fd);
352                 pp->io.fd = -1;
353                 free(up);
354                 return (0);
355         }
356
357         /*
358          * Initialize miscellaneous variables
359          */
360         pp->unitptr = up;
361         pp->clockdesc = DESCRIPTION;
362
363         peer->precision = PRECISION;
364         peer->sstclktype = CTL_SST_TS_UHF;
365         peer->minpoll = TRMB_MINPOLL;
366         peer->maxpoll = TRMB_MAXPOLL;
367         memcpy((char *)&pp->refid, REFID, 4);
368         
369         up->leap_status = 0;
370         up->unit = (short) unit;
371         up->rpt_status = TSIP_PARSED_EMPTY;
372         up->rpt_cnt = 0;
373
374         if (up->type == CLK_THUNDERBOLT)
375                 init_thunderbolt(fd);
376         if (up->type == CLK_ACUTIME)
377                 init_acutime(fd);
378
379         return 1;
380 }
381
382
383 /*
384  * palisade_shutdown - shut down the clock
385  */
386 static void
387 palisade_shutdown (
388         int unit,
389         struct peer *peer
390         )
391 {
392         struct palisade_unit *up;
393         struct refclockproc *pp;
394         pp = peer->procptr;
395         up = pp->unitptr;
396         if (-1 != pp->io.fd)
397                 io_closeclock(&pp->io);
398         if (NULL != up)
399                 free(up);
400 }
401
402
403
404 /* 
405  * unpack_date - get day and year from date
406  */
407 int
408 day_of_year (
409         char * dt
410         )
411 {
412         int day, mon, year;
413
414         mon = dt[1];
415         /* Check month is inside array bounds */
416         if ((mon < 1) || (mon > 12)) 
417                 return -1;
418
419         day = dt[0] + days_of_year[mon - 1];
420         year = getint((u_char *) (dt + 2)); 
421
422         if ( !(year % 4) && ((year % 100) || 
423                              (!(year % 100) && !(year%400)))
424              &&(mon > 2))
425                 day ++; /* leap year and March or later */
426
427         return day;
428 }
429
430
431 /* 
432  * TSIP_decode - decode the TSIP data packets 
433  */
434 int
435 TSIP_decode (
436         struct peer *peer
437         )
438 {
439         int st;
440         long   secint;
441         double secs;
442         double secfrac;
443         unsigned short event = 0;
444
445         struct palisade_unit *up;
446         struct refclockproc *pp;
447
448         pp = peer->procptr;
449         up = pp->unitptr;
450
451         /*
452          * Check the time packet, decode its contents. 
453          * If the timecode has invalid length or is not in
454          * proper format, declare bad format and exit.
455          */
456
457         if ((up->type != CLK_THUNDERBOLT) & (up->type != CLK_ACUTIME)){
458                 if ((up->rpt_buf[0] == (char) 0x41) ||
459                     (up->rpt_buf[0] == (char) 0x46) ||
460                     (up->rpt_buf[0] == (char) 0x54) ||
461                     (up->rpt_buf[0] == (char) 0x4B) ||
462                     (up->rpt_buf[0] == (char) 0x6D)) {
463
464                         /* standard time packet - GPS time and GPS week number */
465 #ifdef DEBUG
466                         printf("Palisade Port B packets detected. Connect to Port A\n");
467 #endif
468
469                         return 0;       
470                 }
471         }
472
473         /*
474          * We cast both to u_char to as 0x8f uses the sign bit on a char
475          */
476         if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
477                 /* 
478                  * Superpackets
479                  */
480                 event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
481                 if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 
482                         /* Ignore Packet */
483                         return 0;          
484         
485                 switch (mb(0) & 0xff) {
486                         int GPS_UTC_Offset;
487                         long tow;
488
489                     case PACKET_8F0B: 
490
491                         if (up->polled <= 0)
492                                 return 0;
493
494                         if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
495                                 break;
496                 
497 #ifdef DEBUG
498                         if (debug > 1) {
499                                 int ts;
500                                 double lat, lon, alt;
501                                 lat = getdbl((u_char *) &mb(42)) * R2D;
502                                 lon = getdbl((u_char *) &mb(50)) * R2D;
503                                 alt = getdbl((u_char *) &mb(58));
504
505                                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
506                                        up->unit, lat,lon,alt);
507                                 printf("TSIP_decode: unit %d: Sats:",
508                                        up->unit);
509                                 for (st = 66, ts = 0; st <= 73; st++)
510                                         if (mb(st)) {
511                                                 if (mb(st) > 0) ts++;
512                                                 printf(" %02d", mb(st));
513                                         }
514                                 printf(" : Tracking %d\n", ts); 
515                         }
516 #endif
517
518                         GPS_UTC_Offset = getint((u_char *) &mb(16));  
519                         if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 
520 #ifdef DEBUG
521                                 printf("TSIP_decode: UTC Offset Unknown\n");
522 #endif
523                                 break;
524                         }
525
526                         secs = getdbl((u_char *) &mb(3));
527                         secint = (long) secs;
528                         secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
529
530                         pp->nsec = (long) (secfrac * 1000000000); 
531
532                         secint %= 86400;    /* Only care about today */
533                         pp->hour = secint / 3600;
534                         secint %= 3600;
535                         pp->minute = secint / 60;
536                         secint %= 60;
537                         pp->second = secint % 60;
538                 
539                         if ((pp->day = day_of_year(&mb(11))) < 0) break;
540
541                         pp->year = getint((u_char *) &mb(13)); 
542
543 #ifdef DEBUG
544                         if (debug > 1)
545                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n",
546                                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
547                                        pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
548 #endif
549                         /* Only use this packet when no
550                          * 8F-AD's are being received
551                          */
552
553                         if (up->leap_status) {
554                                 up->leap_status = 0;
555                                 return 0;
556                         }
557
558                         return 2;
559                         break;
560
561                     case PACKET_NTP:
562                         /* Palisade-NTP Packet */
563
564                         if (up->rpt_cnt != LENCODE_NTP) /* check length */
565                                 break;
566         
567                         up->leap_status = mb(19);
568
569                         if (up->polled  <= 0) 
570                                 return 0;
571                                 
572                         /* Check Tracking Status */
573                         st = mb(18);
574                         if (st < 0 || st > 14)
575                                 st = 14;
576                         if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
577 #ifdef DEBUG
578                                 printf("TSIP_decode: Not Tracking Sats : %s\n",
579                                        *Tracking_Status[st]);
580 #endif
581                                 refclock_report(peer, CEVNT_BADTIME);
582                                 up->polled = -1;
583                                 return 0;
584                                 break;
585                         }
586
587                         up->month = mb(15);
588                         if ( (up->leap_status & PALISADE_LEAP_PENDING) &&
589                         /* Avoid early announce: https://bugs.ntp.org/2773 */
590                                 (6 == up->month || 12 == up->month) ) {
591                                 if (up->leap_status & PALISADE_UTC_TIME)  
592                                         pp->leap = LEAP_ADDSECOND;
593                                 else
594                                         pp->leap = LEAP_DELSECOND;
595                         }
596                         else if (up->leap_status)
597                                 pp->leap = LEAP_NOWARNING;
598                 
599                         else {  /* UTC flag is not set:
600                                  * Receiver may have been reset, and lost
601                                  * its UTC almanac data */
602                                 pp->leap = LEAP_NOTINSYNC;
603 #ifdef DEBUG
604                                 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
605                                        mb(19)); 
606 #endif
607                                 refclock_report(peer, CEVNT_BADTIME);
608                                 up->polled = -1;
609                                 return 0;
610                         }
611
612                         pp->nsec = (long) (getdbl((u_char *) &mb(3))
613                                            * 1000000000);
614
615                         if ((pp->day = day_of_year(&mb(14))) < 0) 
616                                 break;
617                         pp->year = getint((u_char *) &mb(16)); 
618                         pp->hour = mb(11);
619                         pp->minute = mb(12);
620                         pp->second = mb(13);
621                         up->month = mb(14);  /* Save for LEAP check */
622
623 #ifdef DEBUG
624                         if (debug > 1)
625                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n",
626                                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
627                                        pp->second, pp->nsec, mb(15), mb(14), pp->year,
628                                        mb(19), *Tracking_Status[st]);
629 #endif
630                         return 1;
631                         break;
632
633                     case PACKET_8FAC:   
634                         if (up->polled <= 0)
635                                 return 0; 
636
637                         if (up->rpt_cnt != LENCODE_8FAC)/* check length */
638                                 break;
639
640 #ifdef DEBUG
641                         if (debug > 1) {
642                                 double lat, lon, alt;
643                                 lat = getdbl((u_char *) &mb(36)) * R2D;
644                                 lon = getdbl((u_char *) &mb(44)) * R2D;
645                                 alt = getdbl((u_char *) &mb(52));
646
647                                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
648                                        up->unit, lat,lon,alt);
649                                 printf("TSIP_decode: unit %d\n", up->unit);
650                         }
651 #endif
652                         if ( (getint((u_char *) &mb(10)) & 0x80) &&
653                         /* Avoid early announce: https://bugs.ntp.org/2773 */
654                             (6 == up->month || 12 == up->month) )
655                                 pp->leap = LEAP_ADDSECOND;  /* we ASSUME addsecond */
656                         else 
657                                 pp->leap = LEAP_NOWARNING;
658
659 #ifdef DEBUG
660                         if (debug > 1) 
661                                 printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
662                                        up->unit, mb(0) & 0xff, pp->leap);
663                         if (debug > 1) {
664                                 printf("Receiver MODE: 0x%02X\n", (u_char)mb(1));
665                                 if (mb(1) == 0x00)
666                                         printf("                AUTOMATIC\n");
667                                 if (mb(1) == 0x01)
668                                         printf("                SINGLE SATELLITE\n");   
669                                 if (mb(1) == 0x03)
670                                         printf("                HORIZONTAL(2D)\n");
671                                 if (mb(1) == 0x04)
672                                         printf("                FULL POSITION(3D)\n");
673                                 if (mb(1) == 0x05)
674                                         printf("                DGPR REFERENCE\n");
675                                 if (mb(1) == 0x06)
676                                         printf("                CLOCK HOLD(2D)\n");
677                                 if (mb(1) == 0x07)
678                                         printf("                OVERDETERMINED CLOCK\n");
679
680                                 printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2));
681                                 if (mb(2) == 0x00)
682                                         printf("                NORMAL\n");
683                                 if (mb(2) == 0x01)
684                                         printf("                POWER-UP\n");
685                                 if (mb(2) == 0x02)
686                                         printf("                AUTO HOLDOVER\n");
687                                 if (mb(2) == 0x03)
688                                         printf("                MANUAL HOLDOVER\n");
689                                 if (mb(2) == 0x04)
690                                         printf("                RECOVERY\n");
691                                 if (mb(2) == 0x06)
692                                         printf("                DISCIPLINING DISABLED\n");
693                         }
694 #endif   
695                         return 0;
696                         break;
697
698                     case PACKET_8FAB:
699                         /* Thunderbolt Primary Timing Packet */
700
701                         if (up->rpt_cnt != LENCODE_8FAB) /* check length */
702                                 break;
703
704                         if (up->polled  <= 0)
705                                 return 0;
706
707                         GPS_UTC_Offset = getint((u_char *) &mb(7));
708
709                         if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
710 #ifdef DEBUG
711                                 printf("TSIP_decode: UTC Offset Unknown\n");
712 #endif
713                                 break;
714                         }
715
716
717                         if ((mb(9) & 0x1d) == 0x0) {
718                                 /* if we know the GPS time and the UTC offset,
719                                    we expect UTC timing information !!! */
720
721                                 pp->leap = LEAP_NOTINSYNC;
722                                 refclock_report(peer, CEVNT_BADTIME);
723                                 up->polled = -1;
724                                 return 0;
725                         }
726
727                         pp->nsec = 0;
728 #ifdef DEBUG            
729                         printf("\nTiming Flags are:\n");
730                         printf("Timing flag value is: 0x%X\n", mb(9));
731                         if ((mb(9) & 0x01) != 0)
732                                 printf ("       Getting UTC time\n");
733                         else
734                                 printf ("       Getting GPS time\n");
735                         if ((mb(9) & 0x02) != 0)
736                                 printf ("       PPS is from UTC\n");
737                         else
738                                 printf ("       PPS is from GPS\n");
739                         if ((mb(9) & 0x04) != 0)
740                                 printf ("       Time is not Set\n");
741                         else
742                                 printf ("       Time is Set\n");
743                         if ((mb(9) & 0x08) != 0)
744                                 printf("        I dont have UTC info\n");
745                         else
746                                 printf ("       I have UTC info\n");
747                         if ((mb(9) & 0x10) != 0)
748                                 printf ("       Time is from USER\n\n");
749                         else
750                                 printf ("       Time is from GPS\n\n"); 
751 #endif          
752
753                         if ((pp->day = day_of_year(&mb(13))) < 0)
754                                 break;
755                         tow = getlong((u_char *) &mb(1));
756 #ifdef DEBUG            
757                         if (debug > 1) {
758                                 printf("pp->day: %d\n", pp->day); 
759                                 printf("TOW: %ld\n", tow);
760                                 printf("DAY: %d\n", mb(13));
761                         }
762 #endif
763                         pp->year = getint((u_char *) &mb(15));
764                         pp->hour = mb(12);
765                         pp->minute = mb(11);
766                         pp->second = mb(10);
767
768
769 #ifdef DEBUG
770                         if (debug > 1)
771                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, pp->nsec, mb(14), mb(13), pp->year);
772 #endif
773                         return 1;
774                         break;
775
776                     default:
777                         /* Ignore Packet */
778                         return 0;
779                 } /* switch */
780         } /* if 8F packets */
781
782         else if (up->rpt_buf[0] == (u_char)0x42) {
783                 printf("0x42\n");
784                 return 0;
785         }
786         else if (up->rpt_buf[0] == (u_char)0x43) {
787                 printf("0x43\n");
788                 return 0;
789         }
790         else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){
791                 printf("Undocumented 0x41 packet on Thunderbolt\n");
792                 return 0;
793         }
794         else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
795 #ifdef DEBUG
796                 printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0)));
797                 printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
798                 printf("GPS UTC-GPS Offser: %ld\n", (long)getlong((u_char *) &mb(6)));
799 #endif
800                 return 0;
801         }
802
803         /* Health Status for Acutime Receiver */
804         else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
805 #ifdef DEBUG
806                 if (debug > 1)
807                 /* Status Codes */
808                         switch (mb(0)) {
809                             case 0x00:
810                                 printf ("Doing Position Fixes\n");
811                                 break;
812                             case 0x01:
813                                 printf ("Do no have GPS time yet\n");
814                                 break;
815                             case 0x03:
816                                 printf ("PDOP is too high\n");
817                                 break;
818                             case 0x08:
819                                 printf ("No usable satellites\n");
820                                 break;
821                             case 0x09:
822                                 printf ("Only 1 usable satellite\n");
823                                 break;
824                             case 0x0A:
825                                 printf ("Only 2 usable satellites\n");
826                                 break;
827                             case 0x0B:
828                                 printf ("Only 3 usable satellites\n");
829                                 break;
830                             case 0x0C:
831                                 printf("The Chosen satellite is unusable\n");
832                                 break;
833                         }
834 #endif
835                 /* Error Codes */
836                 if (mb(1) != 0) {
837                         
838                         refclock_report(peer, CEVNT_BADTIME);
839                         up->polled = -1;
840 #ifdef DEBUG
841                         if (debug > 1) {
842                                 if (mb(1) & 0x01)
843                                         printf ("Signal Processor Error, reset unit.\n");
844                                 if (mb(1) & 0x02)
845                                         printf ("Alignment error, channel or chip 1, reset unit.\n");
846                                 if (mb(1) & 0x03)
847                                         printf ("Alignment error, channel or chip 2, reset unit.\n");
848                                 if (mb(1) & 0x04)
849                                         printf ("Antenna feed line fault (open or short)\n");
850                                 if (mb(1) & 0x05)
851                                         printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
852                         }
853 #endif
854                 
855                 return 0;
856                 }
857         }
858         else if (up->rpt_buf[0] == 0x54)
859                 return 0;
860
861         else if (up->rpt_buf[0] == PACKET_6D) {
862 #ifdef DEBUG
863                 int sats;
864
865                 if ((mb(0) & 0x01) && (mb(0) & 0x02))
866                         printf("2d Fix Dimension\n");
867                 if (mb(0) & 0x04)
868                         printf("3d Fix Dimension\n");
869
870                 if (mb(0) & 0x08)
871                         printf("Fix Mode is MANUAL\n");
872                 else
873                         printf("Fix Mode is AUTO\n");
874         
875                 sats = mb(0) & 0xF0;
876                 sats = sats >> 4;
877                 printf("Tracking %d Satellites\n", sats);
878 #endif
879                 return 0;
880         } /* else if not super packet */
881         refclock_report(peer, CEVNT_BADREPLY);
882         up->polled = -1;
883 #ifdef DEBUG
884         printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 
885                up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 
886                event, up->rpt_cnt);
887 #endif
888         return 0;
889 }
890
891 /*
892  * palisade__receive - receive data from the serial interface
893  */
894
895 static void
896 palisade_receive (
897         struct peer * peer
898         )
899 {
900         struct palisade_unit *up;
901         struct refclockproc *pp;
902
903         /*
904          * Initialize pointers and read the timecode and timestamp.
905          */
906         pp = peer->procptr;
907         up = pp->unitptr;
908                 
909         if (! TSIP_decode(peer)) return;
910         
911         if (up->polled <= 0) 
912                 return;   /* no poll pending, already received or timeout */
913
914         up->polled = 0;  /* Poll reply received */
915         pp->lencode = 0; /* clear time code */
916 #ifdef DEBUG
917         if (debug) 
918                 printf(
919                         "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
920                         up->unit, pp->year, pp->day, pp->hour, pp->minute, 
921                         pp->second, pp->nsec);
922 #endif
923
924         /*
925          * Process the sample
926          * Generate timecode: YYYY DoY HH:MM:SS.microsec 
927          * report and process 
928          */
929
930         snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
931                  "%4d %03d %02d:%02d:%02d.%09ld",
932                  pp->year, pp->day,
933                  pp->hour,pp->minute, pp->second, pp->nsec); 
934         pp->lencode = 24;
935
936         if (!refclock_process(pp)) {
937                 refclock_report(peer, CEVNT_BADTIME);
938
939 #ifdef DEBUG
940                 printf("palisade_receive: unit %d: refclock_process failed!\n",
941                        up->unit);
942 #endif
943                 return;
944         }
945
946         record_clock_stats(&peer->srcadr, pp->a_lastcode); 
947
948 #ifdef DEBUG
949         if (debug)
950                 printf("palisade_receive: unit %d: %s\n",
951                        up->unit, prettydate(&pp->lastrec));
952 #endif
953         pp->lastref = pp->lastrec;
954         refclock_receive(peer);
955 }
956
957
958 /*
959  * palisade_poll - called by the transmit procedure
960  *
961  */
962 static void
963 palisade_poll (
964         int unit,
965         struct peer *peer
966         )
967 {
968         struct palisade_unit *up;
969         struct refclockproc *pp;
970         
971         pp = peer->procptr;
972         up = pp->unitptr;
973
974         pp->polls++;
975         if (up->polled > 0) /* last reply never arrived or error */ 
976                 refclock_report(peer, CEVNT_TIMEOUT);
977
978         up->polled = 2; /* synchronous packet + 1 event */
979         
980 #ifdef DEBUG
981         if (debug)
982                 printf("palisade_poll: unit %d: polling %s\n", unit,
983                        (pp->sloppyclockflag & CLK_FLAG2) ? 
984                        "synchronous packet" : "event");
985 #endif 
986
987         if (pp->sloppyclockflag & CLK_FLAG2) 
988                 return;  /* using synchronous packet input */
989
990         if(up->type == CLK_PRAECIS) {
991                 if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
992                         msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
993                 else {
994                         praecis_msg = 1;
995                         return;
996                 }
997         }
998
999         if (HW_poll(pp) < 0) 
1000                 refclock_report(peer, CEVNT_FAULT); 
1001 }
1002
1003 static void
1004 praecis_parse (
1005         struct recvbuf *rbufp,
1006         struct peer *peer
1007         )
1008 {
1009         static char buf[100];
1010         static int p = 0;
1011         struct refclockproc *pp;
1012
1013         pp = peer->procptr;
1014
1015         memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
1016         p += rbufp->recv_length;
1017
1018         if(buf[p-2] == '\r' && buf[p-1] == '\n') {
1019                 buf[p-2] = '\0';
1020                 record_clock_stats(&peer->srcadr, buf);
1021
1022                 p = 0;
1023                 praecis_msg = 0;
1024
1025                 if (HW_poll(pp) < 0)
1026                         refclock_report(peer, CEVNT_FAULT);
1027
1028         }
1029 }
1030
1031 static void
1032 palisade_io (
1033         struct recvbuf *rbufp
1034         )
1035 {
1036         /*
1037          * Initialize pointers and read the timecode and timestamp.
1038          */
1039         struct palisade_unit *up;
1040         struct refclockproc *pp;
1041         struct peer *peer;
1042
1043         char * c, * d;
1044
1045         peer = rbufp->recv_peer;
1046         pp = peer->procptr;
1047         up = pp->unitptr;
1048
1049         if(up->type == CLK_PRAECIS) {
1050                 if(praecis_msg) {
1051                         praecis_parse(rbufp,peer);
1052                         return;
1053                 }
1054         }
1055
1056         c = (char *) &rbufp->recv_space;
1057         d = c + rbufp->recv_length;
1058                 
1059         while (c != d) {
1060
1061                 /* Build time packet */
1062                 switch (up->rpt_status) {
1063
1064                     case TSIP_PARSED_DLE_1:
1065                         switch (*c)
1066                         {
1067                             case 0:
1068                             case DLE:
1069                             case ETX:
1070                                 up->rpt_status = TSIP_PARSED_EMPTY;
1071                                 break;
1072
1073                             default:
1074                                 up->rpt_status = TSIP_PARSED_DATA;
1075                                 /* save packet ID */
1076                                 up->rpt_buf[0] = *c;
1077                                 break;
1078                         }
1079                         break;
1080
1081                     case TSIP_PARSED_DATA:
1082                         if (*c == DLE)
1083                                 up->rpt_status = TSIP_PARSED_DLE_2;
1084                         else 
1085                                 mb(up->rpt_cnt++) = *c;
1086                         break;
1087
1088                     case TSIP_PARSED_DLE_2:
1089                         if (*c == DLE) {
1090                                 up->rpt_status = TSIP_PARSED_DATA;
1091                                 mb(up->rpt_cnt++) = 
1092                                     *c;
1093                         }
1094                         else if (*c == ETX) 
1095                                 up->rpt_status = TSIP_PARSED_FULL;
1096                         else    {
1097                                 /* error: start new report packet */
1098                                 up->rpt_status = TSIP_PARSED_DLE_1;
1099                                 up->rpt_buf[0] = *c;
1100                         }
1101                         break;
1102
1103                     case TSIP_PARSED_FULL:
1104                     case TSIP_PARSED_EMPTY:
1105                     default:
1106                         if ( *c != DLE)
1107                                 up->rpt_status = TSIP_PARSED_EMPTY;
1108                         else 
1109                                 up->rpt_status = TSIP_PARSED_DLE_1;
1110                         break;
1111                 }
1112                 
1113                 c++;
1114
1115                 if (up->rpt_status == TSIP_PARSED_DLE_1) {
1116                         up->rpt_cnt = 0;
1117                         if (pp->sloppyclockflag & CLK_FLAG2) 
1118                                 /* stamp it */
1119                                 get_systime(&pp->lastrec);
1120                 }
1121                 else if (up->rpt_status == TSIP_PARSED_EMPTY)
1122                         up->rpt_cnt = 0;
1123
1124                 else if (up->rpt_cnt > BMAX) 
1125                         up->rpt_status =TSIP_PARSED_EMPTY;
1126
1127                 if (up->rpt_status == TSIP_PARSED_FULL) 
1128                         palisade_receive(peer);
1129
1130         } /* while chars in buffer */
1131 }
1132
1133
1134 /*
1135  * Trigger the Palisade's event input, which is driven off the RTS
1136  *
1137  * Take a system time stamp to match the GPS time stamp.
1138  *
1139  */
1140 long
1141 HW_poll (
1142         struct refclockproc * pp        /* pointer to unit structure */
1143         )
1144 {       
1145         int x;  /* state before & after RTS set */
1146         struct palisade_unit *up;
1147
1148         up = pp->unitptr;
1149
1150         /* read the current status, so we put things back right */
1151         if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1152                 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1153                         up->unit));
1154                 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 
1155                         up->unit);
1156                 return -1;
1157         }
1158   
1159         x |= TIOCM_RTS;        /* turn on RTS  */
1160
1161         /* Edge trigger */
1162         if (up->type == CLK_ACUTIME)
1163                 write (pp->io.fd, "", 1);
1164                 
1165         if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 
1166 #ifdef DEBUG
1167                 if (debug)
1168                         printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1169 #endif
1170                 msyslog(LOG_ERR,
1171                         "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 
1172                         up->unit);
1173                 return -1;
1174         }
1175
1176         x &= ~TIOCM_RTS;        /* turn off RTS  */
1177         
1178         /* poll timestamp */
1179         get_systime(&pp->lastrec);
1180
1181         if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1182 #ifdef DEBUG
1183                 if (debug)
1184                         printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1185 #endif
1186                 msyslog(LOG_ERR,
1187                         "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 
1188                         up->unit);
1189                 return -1;
1190         }
1191
1192         return 0;
1193 }
1194
1195 /*
1196  * copy/swap a big-endian palisade double into a host double
1197  */
1198 static double
1199 getdbl (
1200         u_char *bp
1201         )
1202 {
1203 #ifdef WORDS_BIGENDIAN
1204         double out;
1205
1206         memcpy(&out, bp, sizeof(out));
1207         return out;
1208 #else
1209         union {
1210                 u_char ch[8];
1211                 u_int32 u32[2];
1212         } ui;
1213                 
1214         union {
1215                 double out;
1216                 u_int32 u32[2];
1217         } uo;
1218
1219         memcpy(ui.ch, bp, sizeof(ui.ch));
1220         /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1221         uo.u32[0] = ntohl(ui.u32[1]);
1222         /* most-significant 32 bits from swapped bp[0] to bp[3] */
1223         uo.u32[1] = ntohl(ui.u32[0]);
1224
1225         return uo.out;
1226 #endif
1227 }
1228
1229 /*
1230  * copy/swap a big-endian palisade short into a host short
1231  */
1232 static short
1233 getint (
1234         u_char *bp
1235         )
1236 {
1237         u_short us;
1238
1239         memcpy(&us, bp, sizeof(us));
1240         return (short)ntohs(us);
1241 }
1242
1243 /*
1244  * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1245  */
1246 static int32
1247 getlong(
1248         u_char *bp
1249         )
1250 {
1251         u_int32 u32;
1252
1253         memcpy(&u32, bp, sizeof(u32));
1254         return (int32)(u_int32)ntohl(u32);
1255 }
1256
1257 #else   /* REFCLOCK && CLOCK_PALISADE*/
1258 int refclock_palisade_c_notempty;
1259 #endif