Annotation of embedaddon/ntp/ntpd/refclock_palisade.c, revision 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>