/contrib/ntp/ntpd/refclock_palisade.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 955 lines · 683 code · 130 blank · 142 comment · 114 complexity · 329659946f86bbe3f60f8639b2197dbe MD5 · raw file

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