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 #ifdef HAVE_CONFIG_H 56 #include "config.h" 57 #endif 58 59 #if defined(SYS_WINNT) 60 #undef close 61 #define close closesocket 62 #endif 63 64 #if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE)) 65 66 #include "refclock_palisade.h" 67 /* Table to get from month to day of the year */ 68 const int days_of_year [12] = { 69 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 70 }; 71 72 #ifdef DEBUG 73 const char * Tracking_Status[15][15] = { 74 { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" }, 75 {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" }, 76 { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" }, 77 { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" }, 78 { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } }; 79 #endif 80 81 /* 82 * Transfer vector 83 */ 84 struct refclock refclock_palisade = { 85 palisade_start, /* start up driver */ 86 palisade_shutdown, /* shut down driver */ 87 palisade_poll, /* transmit poll message */ 88 noentry, /* not used */ 89 noentry, /* initialize driver (not used) */ 90 noentry, /* not used */ 91 NOFLAGS /* not used */ 92 }; 93 94 int day_of_year P((char *dt)); 95 96 /* Extract the clock type from the mode setting */ 97 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F)) 98 99 /* Supported clock types */ 100 #define CLK_TRIMBLE 0 /* Trimble Palisade */ 101 #define CLK_PRAECIS 1 /* Endrun Technologies Praecis */ 102 103 int praecis_msg; 104 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer); 105 106 /* 107 * palisade_start - open the devices and initialize data for processing 108 */ 109 static int 110 palisade_start ( 111 #ifdef PALISADE 112 unit, peer 113 ) 114 int unit; 115 struct peer *peer; 116 #else /* ANSI */ 117 int unit, 118 struct peer *peer 119 ) 120 #endif 121 { 122 struct palisade_unit *up; 123 struct refclockproc *pp; 124 int fd; 125 char gpsdev[20]; 126 127 struct termios tio; 128 #ifdef SYS_WINNT 129 (void) sprintf(gpsdev, "COM%d:", unit); 130 #else 131 (void) sprintf(gpsdev, DEVICE, unit); 132 #endif 133 /* 134 * Open serial port. 135 */ 136 #if defined PALISADE 137 fd = open(gpsdev, O_RDWR 138 #ifdef O_NONBLOCK 139 | O_NONBLOCK 140 #endif 141 ); 142 #else /* NTP 4.x */ 143 fd = refclock_open(gpsdev, SPEED232, LDISC_RAW); 144 #endif 145 if (fd <= 0) { 146 #ifdef DEBUG 147 printf("Palisade(%d) start: open %s failed\n", unit, gpsdev); 148 #endif 149 return 0; 150 } 151 152 msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd, 153 gpsdev); 154 155 #if defined PALISADE 156 tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); 157 tio.c_iflag = (IGNBRK); 158 tio.c_oflag = (0); 159 tio.c_lflag = (0); 160 161 if (cfsetispeed(&tio, SPEED232) == -1) { 162 msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit); 163 #ifdef DEBUG 164 printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit); 165 #endif 166 return 0; 167 } 168 if (cfsetospeed(&tio, SPEED232) == -1) { 169 #ifdef DEBUG 170 printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit); 171 #endif 172 msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit); 173 return 0; 174 } 175 #else /* NTP 4.x */ 176 if (tcgetattr(fd, &tio) < 0) { 177 msyslog(LOG_ERR, 178 "Palisade(%d) tcgetattr(fd, &tio): %m",unit); 179 #ifdef DEBUG 180 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit); 181 #endif 182 return (0); 183 } 184 185 tio.c_cflag |= (PARENB|PARODD); 186 tio.c_iflag &= ~ICRNL; 187 #endif /* NTP 4.x */ 188 189 if (tcsetattr(fd, TCSANOW, &tio) == -1) { 190 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit); 191 #ifdef DEBUG 192 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit); 193 #endif 194 return 0; 195 } 196 197 /* 198 * Allocate and initialize unit structure 199 */ 200 up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit)); 201 202 if (!(up)) { 203 msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit); 204 #ifdef DEBUG 205 printf("Palisade(%d) emalloc\n",unit); 206 #endif 207 (void) close(fd); 208 return (0); 209 } 210 211 memset((char *)up, 0, sizeof(struct palisade_unit)); 212 213 up->type = CLK_TYPE(peer); 214 switch (up->type) { 215 case CLK_TRIMBLE: 216 /* Normal mode, do nothing */ 217 break; 218 case CLK_PRAECIS: 219 msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled\n",unit); 220 break; 221 default: 222 msyslog(LOG_NOTICE, "Palisade(%d) mode unknown\n",unit); 223 break; 224 } 225 226 pp = peer->procptr; 227 pp->io.clock_recv = palisade_io; 228 pp->io.srcclock = (caddr_t)peer; 229 pp->io.datalen = 0; 230 pp->io.fd = fd; 231 if (!io_addclock(&pp->io)) { 232 #ifdef DEBUG 233 printf("Palisade(%d) io_addclock\n",unit); 234 #endif 235 (void) close(fd); 236 free(up); 237 return (0); 238 } 239 240 /* 241 * Initialize miscellaneous variables 242 */ 243 pp->unitptr = (caddr_t)up; 244 pp->clockdesc = DESCRIPTION; 245 246 peer->precision = PRECISION; 247 peer->sstclktype = CTL_SST_TS_UHF; 248 peer->minpoll = TRMB_MINPOLL; 249 peer->maxpoll = TRMB_MAXPOLL; 250 memcpy((char *)&pp->refid, REFID, 4); 251 252 up->leap_status = 0; 253 up->unit = (short) unit; 254 up->rpt_status = TSIP_PARSED_EMPTY; 255 up->rpt_cnt = 0; 256 257 return 1; 258 } 259 260 261 /* 262 * palisade_shutdown - shut down the clock 263 */ 264 static void 265 palisade_shutdown ( 266 #ifdef PALISADE 267 unit, peer 268 ) 269 int unit; 270 struct peer *peer; 271 #else /* ANSI */ 272 int unit, 273 struct peer *peer 274 ) 275 #endif 276 { 277 struct palisade_unit *up; 278 struct refclockproc *pp; 279 pp = peer->procptr; 280 up = (struct palisade_unit *)pp->unitptr; 281 io_closeclock(&pp->io); 282 free(up); 283 } 284 285 286 287 /* 288 * unpack_date - get day and year from date 289 */ 290 int 291 day_of_year ( 292 #ifdef PALISADE 293 dt 294 ) 295 char * dt; 296 #else 297 char * dt 298 ) 299 #endif 300 { 301 int day, mon, year; 302 303 mon = dt[1]; 304 /* Check month is inside array bounds */ 305 if ((mon < 1) || (mon > 12)) 306 return -1; 307 308 day = dt[0] + days_of_year[mon - 1]; 309 year = getint((u_char *) (dt + 2)); 310 311 if ( !(year % 4) && ((year % 100) || 312 (!(year % 100) && !(year%400))) 313 &&(mon > 2)) 314 day ++; /* leap year and March or later */ 315 316 return day; 317 } 318 319 320 /* 321 * TSIP_decode - decode the TSIP data packets 322 */ 323 int 324 TSIP_decode ( 325 #ifdef PALISADE 326 peer 327 ) 328 struct peer *peer; 329 #else 330 struct peer *peer 331 ) 332 #endif 333 { 334 int st; 335 long secint; 336 double secs; 337 double secfrac; 338 unsigned short event = 0; 339 340 struct palisade_unit *up; 341 struct refclockproc *pp; 342 343 pp = peer->procptr; 344 up = (struct palisade_unit *)pp->unitptr; 345 346 /* 347 * Check the time packet, decode its contents. 348 * If the timecode has invalid length or is not in 349 * proper format, declare bad format and exit. 350 */ 351 352 if ((up->rpt_buf[0] == (char) 0x41) || 353 (up->rpt_buf[0] == (char) 0x46) || 354 (up->rpt_buf[0] == (char) 0x54) || 355 (up->rpt_buf[0] == (char) 0x4B) || 356 (up->rpt_buf[0] == (char) 0x6D)) { 357 358 /* standard time packet - GPS time and GPS week number */ 359 #ifdef DEBUG 360 printf("Palisade Port B packets detected. Connect to Port A\n"); 361 #endif 362 363 return 0; 364 } 365 366 /* 367 * We cast both to u_char to as 0x8f uses the sign bit on a char 368 */ 369 if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) { 370 /* 371 * Superpackets 372 */ 373 event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff); 374 if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 375 /* Ignore Packet */ 376 return 0; 377 378 switch (mb(0) & 0xff) { 379 int GPS_UTC_Offset; 380 case PACKET_8F0B: 381 382 if (up->polled <= 0) 383 return 0; 384 385 if (up->rpt_cnt != LENCODE_8F0B) /* check length */ 386 break; 387 388 #ifdef DEBUG 389 if (debug > 1) { 390 int ts; 391 double lat, lon, alt; 392 lat = getdbl((u_char *) &mb(42)) * R2D; 393 lon = getdbl((u_char *) &mb(50)) * R2D; 394 alt = getdbl((u_char *) &mb(58)); 395 396 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", 397 up->unit, lat,lon,alt); 398 printf("TSIP_decode: unit %d: Sats:", up->unit); 399 for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) { 400 if (mb(st) > 0) ts++; 401 printf(" %02d", mb(st)); 402 } 403 printf(" : Tracking %d\n", ts); 404 } 405 #endif 406 407 GPS_UTC_Offset = getint((u_char *) &mb(16)); 408 if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 409 #ifdef DEBUG 410 printf("TSIP_decode: UTC Offset Unknown\n"); 411 #endif 412 break; 413 } 414 415 secs = getdbl((u_char *) &mb(3)); 416 secint = (long) secs; 417 secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */ 418 419 pp->nsec = (long) (secfrac * 1000000000); 420 421 secint %= 86400; /* Only care about today */ 422 pp->hour = secint / 3600; 423 secint %= 3600; 424 pp->minute = secint / 60; 425 secint %= 60; 426 pp->second = secint % 60; 427 428 if ((pp->day = day_of_year(&mb(11))) < 0) break; 429 430 pp->year = getint((u_char *) &mb(13)); 431 432 #ifdef DEBUG 433 if (debug > 1) 434 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n", 435 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 436 pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset); 437 #endif 438 /* Only use this packet when no 439 * 8F-AD's are being received 440 */ 441 442 if (up->leap_status) { 443 up->leap_status = 0; 444 return 0; 445 } 446 447 return 2; 448 break; 449 450 case PACKET_NTP: 451 /* Palisade-NTP Packet */ 452 453 if (up->rpt_cnt != LENCODE_NTP) /* check length */ 454 break; 455 456 up->leap_status = mb(19); 457 458 if (up->polled <= 0) 459 return 0; 460 461 /* Check Tracking Status */ 462 st = mb(18); 463 if (st < 0 || st > 14) st = 14; 464 if ((st >= 2 && st <= 7) || st == 11 || st == 12) { 465 #ifdef DEBUG 466 printf("TSIP_decode: Not Tracking Sats : %s\n", 467 *Tracking_Status[st]); 468 #endif 469 refclock_report(peer, CEVNT_BADTIME); 470 up->polled = -1; 471 return 0; 472 break; 473 } 474 475 if (up->leap_status & PALISADE_LEAP_PENDING) { 476 if (up->leap_status & PALISADE_UTC_TIME) 477 pp->leap = LEAP_ADDSECOND; 478 else 479 pp->leap = LEAP_DELSECOND; 480 } 481 else if (up->leap_status) 482 pp->leap = LEAP_NOWARNING; 483 484 else { /* UTC flag is not set: 485 * Receiver may have been reset, and lost 486 * its UTC almanac data */ 487 pp->leap = LEAP_NOTINSYNC; 488 #ifdef DEBUG 489 printf("TSIP_decode: UTC Almanac unavailable: %d\n", 490 mb(19)); 491 #endif 492 refclock_report(peer, CEVNT_BADTIME); 493 up->polled = -1; 494 return 0; 495 } 496 497 pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000000); 498 499 if ((pp->day = day_of_year(&mb(14))) < 0) 500 break; 501 pp->year = getint((u_char *) &mb(16)); 502 pp->hour = mb(11); 503 pp->minute = mb(12); 504 pp->second = mb(13); 505 506 #ifdef DEBUG 507 if (debug > 1) 508 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n", 509 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 510 pp->second, pp->nsec, mb(15), mb(14), pp->year, 511 mb(19), *Tracking_Status[st]); 512 #endif 513 return 1; 514 break; 515 516 default: 517 /* Ignore Packet */ 518 return 0; 519 } /* switch */ 520 }/* if 8F packets */ 521 522 refclock_report(peer, CEVNT_BADREPLY); 523 up->polled = -1; 524 #ifdef DEBUG 525 printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 526 up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 527 event, up->rpt_cnt); 528 #endif 529 return 0; 530 } 531 532 /* 533 * palisade__receive - receive data from the serial interface 534 */ 535 536 static void 537 palisade_receive ( 538 #ifdef PALISADE 539 peer 540 ) 541 struct peer * peer; 542 #else /* ANSI */ 543 struct peer * peer 544 ) 545 #endif 546 { 547 struct palisade_unit *up; 548 struct refclockproc *pp; 549 550 /* 551 * Initialize pointers and read the timecode and timestamp. 552 */ 553 pp = peer->procptr; 554 up = (struct palisade_unit *)pp->unitptr; 555 556 if (! TSIP_decode(peer)) return; 557 558 if (up->polled <= 0) 559 return; /* no poll pending, already received or timeout */ 560 561 up->polled = 0; /* Poll reply received */ 562 pp->lencode = 0; /* clear time code */ 563 #ifdef DEBUG 564 if (debug) 565 printf( 566 "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n", 567 up->unit, pp->year, pp->day, pp->hour, pp->minute, 568 pp->second, pp->nsec); 569 #endif 570 571 /* 572 * Process the sample 573 * Generate timecode: YYYY DoY HH:MM:SS.microsec 574 * report and process 575 */ 576 577 (void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld", 578 pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->nsec); 579 pp->lencode = 24; 580 581 #ifdef PALISADE 582 pp->lasttime = current_time; 583 #endif 584 if (!refclock_process(pp 585 #ifdef PALISADE 586 , PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5 587 #endif 588 )) { 589 refclock_report(peer, CEVNT_BADTIME); 590 591 #ifdef DEBUG 592 printf("palisade_receive: unit %d: refclock_process failed!\n", 593 up->unit); 594 #endif 595 return; 596 } 597 598 record_clock_stats(&peer->srcadr, pp->a_lastcode); 599 600 #ifdef DEBUG 601 if (debug) 602 printf("palisade_receive: unit %d: %s\n", 603 up->unit, prettydate(&pp->lastrec)); 604 #endif 605 pp->lastref = pp->lastrec; 606 refclock_receive(peer 607 #ifdef PALISADE 608 , &pp->offset, 0, pp->dispersion, 609 &pp->lastrec, &pp->lastrec, pp->leap 610 #endif 611 ); 612 } 613 614 615 /* 616 * palisade_poll - called by the transmit procedure 617 * 618 */ 619 static void 620 palisade_poll ( 621 #ifdef PALISADE 622 unit, peer 623 ) 624 int unit; 625 struct peer *peer; 626 #else 627 int unit, 628 struct peer *peer 629 ) 630 #endif 631 { 632 struct palisade_unit *up; 633 struct refclockproc *pp; 634 635 pp = peer->procptr; 636 up = (struct palisade_unit *)pp->unitptr; 637 638 pp->polls++; 639 if (up->polled > 0) /* last reply never arrived or error */ 640 refclock_report(peer, CEVNT_TIMEOUT); 641 642 up->polled = 2; /* synchronous packet + 1 event */ 643 644 #ifdef DEBUG 645 if (debug) 646 printf("palisade_poll: unit %d: polling %s\n", unit, 647 (pp->sloppyclockflag & CLK_FLAG2) ? 648 "synchronous packet" : "event"); 649 #endif 650 651 if (pp->sloppyclockflag & CLK_FLAG2) 652 return; /* using synchronous packet input */ 653 654 if(up->type == CLK_PRAECIS) { 655 if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) 656 msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit); 657 else { 658 praecis_msg = 1; 659 return; 660 } 661 } 662 663 if (HW_poll(pp) < 0) 664 refclock_report(peer, CEVNT_FAULT); 665 } 666 667 static void 668 praecis_parse(struct recvbuf *rbufp, struct peer *peer) 669 { 670 static char buf[100]; 671 static int p = 0; 672 struct refclockproc *pp; 673 674 pp = peer->procptr; 675 676 memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length); 677 p += rbufp->recv_length; 678 679 if(buf[p-2] == '\r' && buf[p-1] == '\n') { 680 buf[p-2] = '\0'; 681 record_clock_stats(&peer->srcadr, buf); 682 683 p = 0; 684 praecis_msg = 0; 685 686 if (HW_poll(pp) < 0) 687 refclock_report(peer, CEVNT_FAULT); 688 689 } 690 } 691 692 static void 693 palisade_io ( 694 #ifdef PALISADE 695 rbufp 696 ) 697 struct recvbuf *rbufp; 698 #else /* ANSI */ 699 struct recvbuf *rbufp 700 ) 701 #endif 702 { 703 /* 704 * Initialize pointers and read the timecode and timestamp. 705 */ 706 struct palisade_unit *up; 707 struct refclockproc *pp; 708 struct peer *peer; 709 710 char * c, * d; 711 712 peer = (struct peer *)rbufp->recv_srcclock; 713 pp = peer->procptr; 714 up = (struct palisade_unit *)pp->unitptr; 715 716 if(up->type == CLK_PRAECIS) { 717 if(praecis_msg) { 718 praecis_parse(rbufp,peer); 719 return; 720 } 721 } 722 723 c = (char *) &rbufp->recv_space; 724 d = c + rbufp->recv_length; 725 726 while (c != d) { 727 728 /* Build time packet */ 729 switch (up->rpt_status) { 730 731 case TSIP_PARSED_DLE_1: 732 switch (*c) 733 { 734 case 0: 735 case DLE: 736 case ETX: 737 up->rpt_status = TSIP_PARSED_EMPTY; 738 break; 739 740 default: 741 up->rpt_status = TSIP_PARSED_DATA; 742 /* save packet ID */ 743 up->rpt_buf[0] = *c; 744 break; 745 } 746 break; 747 748 case TSIP_PARSED_DATA: 749 if (*c == DLE) 750 up->rpt_status = TSIP_PARSED_DLE_2; 751 else 752 mb(up->rpt_cnt++) = *c; 753 break; 754 755 case TSIP_PARSED_DLE_2: 756 if (*c == DLE) { 757 up->rpt_status = TSIP_PARSED_DATA; 758 mb(up->rpt_cnt++) = 759 *c; 760 } 761 else if (*c == ETX) 762 up->rpt_status = TSIP_PARSED_FULL; 763 else { 764 /* error: start new report packet */ 765 up->rpt_status = TSIP_PARSED_DLE_1; 766 up->rpt_buf[0] = *c; 767 } 768 break; 769 770 case TSIP_PARSED_FULL: 771 case TSIP_PARSED_EMPTY: 772 default: 773 if ( *c != DLE) 774 up->rpt_status = TSIP_PARSED_EMPTY; 775 else 776 up->rpt_status = TSIP_PARSED_DLE_1; 777 break; 778 } 779 780 c++; 781 782 if (up->rpt_status == TSIP_PARSED_DLE_1) { 783 up->rpt_cnt = 0; 784 if (pp->sloppyclockflag & CLK_FLAG2) 785 /* stamp it */ 786 get_systime(&pp->lastrec); 787 } 788 else if (up->rpt_status == TSIP_PARSED_EMPTY) 789 up->rpt_cnt = 0; 790 791 else if (up->rpt_cnt > BMAX) 792 up->rpt_status =TSIP_PARSED_EMPTY; 793 794 if (up->rpt_status == TSIP_PARSED_FULL) 795 palisade_receive(peer); 796 797 } /* while chars in buffer */ 798 } 799 800 801 /* 802 * Trigger the Palisade's event input, which is driven off the RTS 803 * 804 * Take a system time stamp to match the GPS time stamp. 805 * 806 */ 807 long 808 HW_poll ( 809 #ifdef PALISADE 810 pp /* pointer to unit structure */ 811 ) 812 struct refclockproc * pp; /* pointer to unit structure */ 813 #else 814 struct refclockproc * pp /* pointer to unit structure */ 815 ) 816 #endif 817 { 818 int x; /* state before & after RTS set */ 819 struct palisade_unit *up; 820 821 up = (struct palisade_unit *) pp->unitptr; 822 823 /* read the current status, so we put things back right */ 824 if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { 825 #ifdef DEBUG 826 if (debug) 827 printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno)); 828 #endif 829 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 830 up->unit); 831 return -1; 832 } 833 834 x |= TIOCM_RTS; /* turn on RTS */ 835 836 /* Edge trigger */ 837 if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 838 #ifdef DEBUG 839 if (debug) 840 printf("Palisade HW_poll: unit %d: SET \n", up->unit); 841 #endif 842 msyslog(LOG_ERR, 843 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 844 up->unit); 845 return -1; 846 } 847 848 x &= ~TIOCM_RTS; /* turn off RTS */ 849 850 /* poll timestamp */ 851 get_systime(&pp->lastrec); 852 853 if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { 854 #ifdef DEBUG 855 if (debug) 856 printf("Palisade HW_poll: unit %d: UNSET \n", up->unit); 857 #endif 858 msyslog(LOG_ERR, 859 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 860 up->unit); 861 return -1; 862 } 863 864 return 0; 865 } 866 867 #if 0 /* unused */ 868 /* 869 * this 'casts' a character array into a float 870 */ 871 float 872 getfloat ( 873 #ifdef PALISADE 874 bp 875 ) 876 u_char *bp; 877 #else 878 u_char *bp 879 ) 880 #endif 881 { 882 float sval; 883 #ifdef WORDS_BIGENDIAN 884 ((char *) &sval)[0] = *bp++; 885 ((char *) &sval)[1] = *bp++; 886 ((char *) &sval)[2] = *bp++; 887 ((char *) &sval)[3] = *bp++; 888 #else 889 ((char *) &sval)[3] = *bp++; 890 ((char *) &sval)[2] = *bp++; 891 ((char *) &sval)[1] = *bp++; 892 ((char *) &sval)[0] = *bp; 893 #endif /* ! XNTP_BIG_ENDIAN */ 894 return sval; 895 } 896 #endif 897 898 /* 899 * this 'casts' a character array into a double 900 */ 901 double 902 getdbl ( 903 #ifdef PALISADE 904 bp 905 ) 906 u_char *bp; 907 #else 908 u_char *bp 909 ) 910 #endif 911 { 912 double dval; 913 #ifdef WORDS_BIGENDIAN 914 ((char *) &dval)[0] = *bp++; 915 ((char *) &dval)[1] = *bp++; 916 ((char *) &dval)[2] = *bp++; 917 ((char *) &dval)[3] = *bp++; 918 ((char *) &dval)[4] = *bp++; 919 ((char *) &dval)[5] = *bp++; 920 ((char *) &dval)[6] = *bp++; 921 ((char *) &dval)[7] = *bp; 922 #else 923 ((char *) &dval)[7] = *bp++; 924 ((char *) &dval)[6] = *bp++; 925 ((char *) &dval)[5] = *bp++; 926 ((char *) &dval)[4] = *bp++; 927 ((char *) &dval)[3] = *bp++; 928 ((char *) &dval)[2] = *bp++; 929 ((char *) &dval)[1] = *bp++; 930 ((char *) &dval)[0] = *bp; 931 #endif /* ! XNTP_BIG_ENDIAN */ 932 return dval; 933 } 934 935 /* 936 * cast a 16 bit character array into a short (16 bit) int 937 */ 938 short 939 getint ( 940 #ifdef PALISADE 941 bp 942 ) 943 u_char *bp; 944 #else 945 u_char *bp 946 ) 947 #endif 948 { 949 return (short) (bp[1] + (bp[0] << 8)); 950 } 951 952 #else 953 int refclock_palisade_bs; 954 #endif /* REFCLOCK */ 955