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