4 * This software was developed by the Software and Component Technologies
5 * group of Trimble Navigation, Ltd.
7 * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Trimble Navigation, Ltd.
21 * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
22 * promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * refclock_palisade - clock driver for the Trimble Palisade GPS
42 * For detailed information on this program, please refer to the html
43 * Refclock 29 page accompanying the NTP distribution.
45 * for questions / bugs / comments, contact:
46 * sven_dietrich@trimble.com
48 * Sven-Thorsten Dietrich
49 * 645 North Mary Avenue
50 * Post Office Box 3642
51 * Sunnyvale, CA 94088-3642
53 * Version 2.45; July 14, 1999
57 * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
58 * Contact: Fernando Pablo Hauscarriaga
59 * E-mail: fernandoph@iar.unlp.edu.ar
60 * Home page: www.iar.unlp.edu.ar/~fernandoph
61 * Instituto Argentino de Radioastronomia
64 * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
65 * now we use mode 2 for decode thunderbolt packets.
66 * Fernando P. Hauscarriaga
68 * 30/08/09: Added support for Trimble Acutime Gold Receiver.
69 * Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
76 #if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
79 extern int async_write(int, const void *, unsigned int);
81 #define write(fd, data, octets) async_write(fd, data, octets)
84 #include "refclock_palisade.h"
85 /* Table to get from month to day of the year */
86 const int days_of_year
[12] = {
87 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
91 const char * Tracking_Status
[15][15] = {
92 { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
93 {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
94 { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
95 { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
96 { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
102 struct refclock refclock_palisade
= {
103 palisade_start
, /* start up driver */
104 palisade_shutdown
, /* shut down driver */
105 palisade_poll
, /* transmit poll message */
106 noentry
, /* not used */
107 noentry
, /* initialize driver (not used) */
108 noentry
, /* not used */
109 NOFLAGS
/* not used */
112 int day_of_year (char *dt
);
114 /* Extract the clock type from the mode setting */
115 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
117 /* Supported clock types */
118 #define CLK_TRIMBLE 0 /* Trimble Palisade */
119 #define CLK_PRAECIS 1 /* Endrun Technologies Praecis */
120 #define CLK_THUNDERBOLT 2 /* Trimble Thunderbolt GPS Receiver */
121 #define CLK_ACUTIME 3 /* Trimble Acutime Gold */
122 #define CLK_ACUTIMEB 4 /* Trimble Actutime Gold Port B */
125 static void praecis_parse(struct recvbuf
*rbufp
, struct peer
*peer
);
127 /* These routines are for sending packets to the Thunderbolt receiver
128 * They are taken from Markus Prosch
131 #ifdef PALISADE_SENDCMD_RESURRECTED
133 * sendcmd - Build data packet for sending
137 struct packettx
*buffer
,
142 *(buffer
->data
+ 1) = (unsigned char)c
;
145 #endif /* PALISADE_SENDCMD_RESURRECTED */
148 * sendsupercmd - Build super data packet for sending
152 struct packettx
*buffer
,
158 *(buffer
->data
+ 1) = (unsigned char)c1
;
159 *(buffer
->data
+ 2) = (unsigned char)c2
;
168 struct packettx
*buffer
,
173 *(buffer
->data
+buffer
->size
++) = DLE
;
174 *(buffer
->data
+buffer
->size
++) = (unsigned char)b
;
182 struct packettx
*buffer
,
186 sendbyte(buffer
, (unsigned char)((a
>>8) & 0xff));
187 sendbyte(buffer
, (unsigned char)(a
& 0xff));
191 * sendetx - Send packet or super packet to the device
195 struct packettx
*buffer
,
201 *(buffer
->data
+buffer
->size
++) = DLE
;
202 *(buffer
->data
+buffer
->size
++) = ETX
;
203 result
= write(fd
, buffer
->data
, (unsigned long)buffer
->size
);
212 * init_thunderbolt - Prepares Thunderbolt receiver to be used with
213 * NTP (also taken from Markus Prosch).
223 tx
.data
= (u_char
*) malloc(100);
226 sendsupercmd (&tx
, 0x8E, 0xA2);
230 /* activate packets 0x8F-AB and 0x8F-AC */
231 sendsupercmd (&tx
, 0x8F, 0xA5);
239 * init_acutime - Prepares Acutime Receiver to be used with NTP
246 /* Disable all outputs, Enable Event-Polling on PortA so
247 we can ask for time packets */
251 tx
.data
= (u_char
*) malloc(100);
253 sendsupercmd(&tx
, 0x8E, 0xA5);
264 * palisade_start - open the devices and initialize data for processing
272 struct palisade_unit
*up
;
273 struct refclockproc
*pp
;
278 (void) sprintf(gpsdev
, DEVICE
, unit
);
283 fd
= refclock_open(gpsdev
, SPEED232
, LDISC_RAW
);
286 printf("Palisade(%d) start: open %s failed\n", unit
, gpsdev
);
291 msyslog(LOG_NOTICE
, "Palisade(%d) fd: %d dev: %s", unit
, fd
,
294 if (tcgetattr(fd
, &tio
) < 0) {
296 "Palisade(%d) tcgetattr(fd, &tio): %m",unit
);
298 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit
);
304 tio
.c_cflag
|= (PARENB
|PARODD
);
305 tio
.c_iflag
&= ~ICRNL
;
308 * Allocate and initialize unit structure
310 up
= (struct palisade_unit
*) emalloc(sizeof(struct palisade_unit
));
312 memset((char *)up
, 0, sizeof(struct palisade_unit
));
314 up
->type
= CLK_TYPE(peer
);
317 /* Normal mode, do nothing */
320 msyslog(LOG_NOTICE
, "Palisade(%d) Praecis mode enabled\n"
323 case CLK_THUNDERBOLT
:
324 msyslog(LOG_NOTICE
, "Palisade(%d) Thunderbolt mode enabled\n"
326 tio
.c_cflag
= (CS8
|CLOCAL
|CREAD
);
329 msyslog(LOG_NOTICE
, "Palisade(%d) Acutime Gold mode enabled\n"
333 msyslog(LOG_NOTICE
, "Palisade(%d) mode unknown\n",unit
);
336 if (tcsetattr(fd
, TCSANOW
, &tio
) == -1) {
337 msyslog(LOG_ERR
, "Palisade(%d) tcsetattr(fd, &tio): %m",unit
);
339 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit
);
347 pp
->io
.clock_recv
= palisade_io
;
348 pp
->io
.srcclock
= (caddr_t
)peer
;
351 if (!io_addclock(&pp
->io
)) {
353 printf("Palisade(%d) io_addclock\n",unit
);
361 * Initialize miscellaneous variables
363 pp
->unitptr
= (caddr_t
)up
;
364 pp
->clockdesc
= DESCRIPTION
;
366 peer
->precision
= PRECISION
;
367 peer
->sstclktype
= CTL_SST_TS_UHF
;
368 peer
->minpoll
= TRMB_MINPOLL
;
369 peer
->maxpoll
= TRMB_MAXPOLL
;
370 memcpy((char *)&pp
->refid
, REFID
, 4);
373 up
->unit
= (short) unit
;
374 up
->rpt_status
= TSIP_PARSED_EMPTY
;
377 if (up
->type
== CLK_THUNDERBOLT
)
378 init_thunderbolt(fd
);
379 if (up
->type
== CLK_ACUTIME
)
387 * palisade_shutdown - shut down the clock
395 struct palisade_unit
*up
;
396 struct refclockproc
*pp
;
398 up
= (struct palisade_unit
*)pp
->unitptr
;
399 io_closeclock(&pp
->io
);
406 * unpack_date - get day and year from date
416 /* Check month is inside array bounds */
417 if ((mon
< 1) || (mon
> 12))
420 day
= dt
[0] + days_of_year
[mon
- 1];
421 year
= getint((u_char
*) (dt
+ 2));
423 if ( !(year
% 4) && ((year
% 100) ||
424 (!(year
% 100) && !(year
%400)))
426 day
++; /* leap year and March or later */
433 * TSIP_decode - decode the TSIP data packets
444 unsigned short event
= 0;
446 struct palisade_unit
*up
;
447 struct refclockproc
*pp
;
450 up
= (struct palisade_unit
*)pp
->unitptr
;
453 * Check the time packet, decode its contents.
454 * If the timecode has invalid length or is not in
455 * proper format, declare bad format and exit.
458 if ((up
->type
!= CLK_THUNDERBOLT
) & (up
->type
!= CLK_ACUTIME
)){
459 if ((up
->rpt_buf
[0] == (char) 0x41) ||
460 (up
->rpt_buf
[0] == (char) 0x46) ||
461 (up
->rpt_buf
[0] == (char) 0x54) ||
462 (up
->rpt_buf
[0] == (char) 0x4B) ||
463 (up
->rpt_buf
[0] == (char) 0x6D)) {
465 /* standard time packet - GPS time and GPS week number */
467 printf("Palisade Port B packets detected. Connect to Port A\n");
475 * We cast both to u_char to as 0x8f uses the sign bit on a char
477 if ((u_char
) up
->rpt_buf
[0] == (u_char
) 0x8f) {
481 event
= (unsigned short) (getint((u_char
*) &mb(1)) & 0xffff);
482 if (!((pp
->sloppyclockflag
& CLK_FLAG2
) || event
))
486 switch (mb(0) & 0xff) {
495 if (up
->rpt_cnt
!= LENCODE_8F0B
) /* check length */
501 double lat
, lon
, alt
;
502 lat
= getdbl((u_char
*) &mb(42)) * R2D
;
503 lon
= getdbl((u_char
*) &mb(50)) * R2D
;
504 alt
= getdbl((u_char
*) &mb(58));
506 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
507 up
->unit
, lat
,lon
,alt
);
508 printf("TSIP_decode: unit %d: Sats:",
510 for (st
= 66, ts
= 0; st
<= 73; st
++)
512 if (mb(st
) > 0) ts
++;
513 printf(" %02d", mb(st
));
515 printf(" : Tracking %d\n", ts
);
519 GPS_UTC_Offset
= getint((u_char
*) &mb(16));
520 if (GPS_UTC_Offset
== 0) { /* Check UTC offset */
522 printf("TSIP_decode: UTC Offset Unknown\n");
527 secs
= getdbl((u_char
*) &mb(3));
528 secint
= (long) secs
;
529 secfrac
= secs
- secint
; /* 0.0 <= secfrac < 1.0 */
531 pp
->nsec
= (long) (secfrac
* 1000000000);
533 secint
%= 86400; /* Only care about today */
534 pp
->hour
= secint
/ 3600;
536 pp
->minute
= secint
/ 60;
538 pp
->second
= secint
% 60;
540 if ((pp
->day
= day_of_year(&mb(11))) < 0) break;
542 pp
->year
= getint((u_char
*) &mb(13));
546 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
547 up
->unit
, mb(0) & 0xff, event
, pp
->hour
, pp
->minute
,
548 pp
->second
, pp
->nsec
, mb(12), mb(11), pp
->year
, GPS_UTC_Offset
);
550 /* Only use this packet when no
551 * 8F-AD's are being received
554 if (up
->leap_status
) {
563 /* Palisade-NTP Packet */
565 if (up
->rpt_cnt
!= LENCODE_NTP
) /* check length */
568 up
->leap_status
= mb(19);
573 /* Check Tracking Status */
575 if (st
< 0 || st
> 14)
577 if ((st
>= 2 && st
<= 7) || st
== 11 || st
== 12) {
579 printf("TSIP_decode: Not Tracking Sats : %s\n",
580 *Tracking_Status
[st
]);
582 refclock_report(peer
, CEVNT_BADTIME
);
588 if (up
->leap_status
& PALISADE_LEAP_PENDING
) {
589 if (up
->leap_status
& PALISADE_UTC_TIME
)
590 pp
->leap
= LEAP_ADDSECOND
;
592 pp
->leap
= LEAP_DELSECOND
;
594 else if (up
->leap_status
)
595 pp
->leap
= LEAP_NOWARNING
;
597 else { /* UTC flag is not set:
598 * Receiver may have been reset, and lost
599 * its UTC almanac data */
600 pp
->leap
= LEAP_NOTINSYNC
;
602 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
605 refclock_report(peer
, CEVNT_BADTIME
);
610 pp
->nsec
= (long) (getdbl((u_char
*) &mb(3))
613 if ((pp
->day
= day_of_year(&mb(14))) < 0)
615 pp
->year
= getint((u_char
*) &mb(16));
622 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
623 up
->unit
, mb(0) & 0xff, event
, pp
->hour
, pp
->minute
,
624 pp
->second
, pp
->nsec
, mb(15), mb(14), pp
->year
,
625 mb(19), *Tracking_Status
[st
]);
634 if (up
->rpt_cnt
!= LENCODE_8FAC
)/* check length */
639 double lat
, lon
, alt
;
640 lat
= getdbl((u_char
*) &mb(36)) * R2D
;
641 lon
= getdbl((u_char
*) &mb(44)) * R2D
;
642 alt
= getdbl((u_char
*) &mb(52));
644 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
645 up
->unit
, lat
,lon
,alt
);
646 printf("TSIP_decode: unit %d\n", up
->unit
);
649 if (getint((u_char
*) &mb(10)) & 0x80)
650 pp
->leap
= LEAP_ADDSECOND
; /* we ASSUME addsecond */
652 pp
->leap
= LEAP_NOWARNING
;
656 printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
657 up
->unit
, mb(0) & 0xff, pp
->leap
);
659 printf("Receiver MODE: 0x%02X\n", (u_char
)mb(1));
661 printf(" AUTOMATIC\n");
663 printf(" SINGLE SATELLITE\n");
665 printf(" HORIZONTAL(2D)\n");
667 printf(" FULL POSITION(3D)\n");
669 printf(" DGPR REFERENCE\n");
671 printf(" CLOCK HOLD(2D)\n");
673 printf(" OVERDETERMINED CLOCK\n");
675 printf("\n** Disciplining MODE 0x%02X:\n", (u_char
)mb(2));
679 printf(" POWER-UP\n");
681 printf(" AUTO HOLDOVER\n");
683 printf(" MANUAL HOLDOVER\n");
685 printf(" RECOVERY\n");
687 printf(" DISCIPLINING DISABLED\n");
694 /* Thunderbolt Primary Timing Packet */
696 if (up
->rpt_cnt
!= LENCODE_8FAB
) /* check length */
702 GPS_UTC_Offset
= getint((u_char
*) &mb(7));
704 if (GPS_UTC_Offset
== 0){ /* Check UTC Offset */
706 printf("TSIP_decode: UTC Offset Unknown\n");
712 if ((mb(9) & 0x1d) == 0x0) {
713 /* if we know the GPS time and the UTC offset,
714 we expect UTC timing information !!! */
716 pp
->leap
= LEAP_NOTINSYNC
;
717 refclock_report(peer
, CEVNT_BADTIME
);
724 printf("\nTiming Flags are:\n");
725 printf("Timing flag value is: 0x%X\n", mb(9));
726 if ((mb(9) & 0x01) != 0)
727 printf (" Getting UTC time\n");
729 printf (" Getting GPS time\n");
730 if ((mb(9) & 0x02) != 0)
731 printf (" PPS is from UTC\n");
733 printf (" PPS is from GPS\n");
734 if ((mb(9) & 0x04) != 0)
735 printf (" Time is not Set\n");
737 printf (" Time is Set\n");
738 if ((mb(9) & 0x08) != 0)
739 printf(" I dont have UTC info\n");
741 printf (" I have UTC info\n");
742 if ((mb(9) & 0x10) != 0)
743 printf (" Time is from USER\n\n");
745 printf (" Time is from GPS\n\n");
748 if ((pp
->day
= day_of_year(&mb(13))) < 0)
750 tow
= getlong((u_char
*) &mb(1));
753 printf("pp->day: %d\n", pp
->day
);
754 printf("TOW: %ld\n", tow
);
755 printf("DAY: %d\n", mb(13));
758 pp
->year
= getint((u_char
*) &mb(15));
766 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
);
775 } /* if 8F packets */
777 else if (up
->rpt_buf
[0] == (u_char
)0x42) {
781 else if (up
->rpt_buf
[0] == (u_char
)0x43) {
785 else if ((up
->rpt_buf
[0] == PACKET_41
) & (up
->type
== CLK_THUNDERBOLT
)){
786 printf("Undocumented 0x41 packet on Thunderbolt\n");
789 else if ((up
->rpt_buf
[0] == PACKET_41A
) & (up
->type
== CLK_ACUTIME
)) {
791 printf("GPS TOW: %ld\n", getlong((u_char
*) &mb(0)));
792 printf("GPS WN: %d\n", getint((u_char
*) &mb(4)));
793 printf("GPS UTC-GPS Offser: %ld\n", getlong((u_char
*) &mb(6)));
798 /* Health Status for Acutime Receiver */
799 else if ((up
->rpt_buf
[0] == PACKET_46
) & (up
->type
== CLK_ACUTIME
)) {
805 printf ("Doing Position Fixes\n");
808 printf ("Do no have GPS time yet\n");
811 printf ("PDOP is too high\n");
814 printf ("No usable satellites\n");
817 printf ("Only 1 usable satellite\n");
820 printf ("Only 2 usable satellites\n");
823 printf ("Only 3 usable satellites\n");
826 printf("The Chosen satellite is unusable\n");
833 refclock_report(peer
, CEVNT_BADTIME
);
838 printf ("Signal Processor Error, reset unit.\n");
840 printf ("Alignment error, channel or chip 1, reset unit.\n");
842 printf ("Alignment error, channel or chip 2, reset unit.\n");
844 printf ("Antenna feed line fault (open or short)\n");
846 printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
853 else if (up
->rpt_buf
[0] == 0x54)
856 else if (up
->rpt_buf
[0] == PACKET_6D
) {
860 if ((mb(0) & 0x01) && (mb(0) & 0x02))
861 printf("2d Fix Dimension\n");
863 printf("3d Fix Dimension\n");
866 printf("Fix Mode is MANUAL\n");
868 printf("Fix Mode is AUTO\n");
872 printf("Tracking %d Satellites\n", sats
);
875 } /* else if not super packet */
876 refclock_report(peer
, CEVNT_BADREPLY
);
879 printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
880 up
->unit
, up
->rpt_buf
[0] & 0xff, mb(0) & 0xff,
887 * palisade__receive - receive data from the serial interface
895 struct palisade_unit
*up
;
896 struct refclockproc
*pp
;
899 * Initialize pointers and read the timecode and timestamp.
902 up
= (struct palisade_unit
*)pp
->unitptr
;
904 if (! TSIP_decode(peer
)) return;
907 return; /* no poll pending, already received or timeout */
909 up
->polled
= 0; /* Poll reply received */
910 pp
->lencode
= 0; /* clear time code */
914 "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
915 up
->unit
, pp
->year
, pp
->day
, pp
->hour
, pp
->minute
,
916 pp
->second
, pp
->nsec
);
921 * Generate timecode: YYYY DoY HH:MM:SS.microsec
925 (void) sprintf(pp
->a_lastcode
,"%4d %03d %02d:%02d:%02d.%06ld",
926 pp
->year
,pp
->day
,pp
->hour
,pp
->minute
, pp
->second
,pp
->nsec
);
929 if (!refclock_process(pp
)) {
930 refclock_report(peer
, CEVNT_BADTIME
);
933 printf("palisade_receive: unit %d: refclock_process failed!\n",
939 record_clock_stats(&peer
->srcadr
, pp
->a_lastcode
);
943 printf("palisade_receive: unit %d: %s\n",
944 up
->unit
, prettydate(&pp
->lastrec
));
946 pp
->lastref
= pp
->lastrec
;
947 refclock_receive(peer
);
952 * palisade_poll - called by the transmit procedure
961 struct palisade_unit
*up
;
962 struct refclockproc
*pp
;
965 up
= (struct palisade_unit
*)pp
->unitptr
;
968 if (up
->polled
> 0) /* last reply never arrived or error */
969 refclock_report(peer
, CEVNT_TIMEOUT
);
971 up
->polled
= 2; /* synchronous packet + 1 event */
975 printf("palisade_poll: unit %d: polling %s\n", unit
,
976 (pp
->sloppyclockflag
& CLK_FLAG2
) ?
977 "synchronous packet" : "event");
980 if (pp
->sloppyclockflag
& CLK_FLAG2
)
981 return; /* using synchronous packet input */
983 if(up
->type
== CLK_PRAECIS
) {
984 if(write(peer
->procptr
->io
.fd
,"SPSTAT\r\n",8) < 0)
985 msyslog(LOG_ERR
, "Palisade(%d) write: %m:",unit
);
993 refclock_report(peer
, CEVNT_FAULT
);
998 struct recvbuf
*rbufp
,
1002 static char buf
[100];
1004 struct refclockproc
*pp
;
1008 memcpy(buf
+p
,rbufp
->recv_space
.X_recv_buffer
, rbufp
->recv_length
);
1009 p
+= rbufp
->recv_length
;
1011 if(buf
[p
-2] == '\r' && buf
[p
-1] == '\n') {
1013 record_clock_stats(&peer
->srcadr
, buf
);
1018 if (HW_poll(pp
) < 0)
1019 refclock_report(peer
, CEVNT_FAULT
);
1026 struct recvbuf
*rbufp
1030 * Initialize pointers and read the timecode and timestamp.
1032 struct palisade_unit
*up
;
1033 struct refclockproc
*pp
;
1038 peer
= (struct peer
*)rbufp
->recv_srcclock
;
1040 up
= (struct palisade_unit
*)pp
->unitptr
;
1042 if(up
->type
== CLK_PRAECIS
) {
1044 praecis_parse(rbufp
,peer
);
1049 c
= (char *) &rbufp
->recv_space
;
1050 d
= c
+ rbufp
->recv_length
;
1054 /* Build time packet */
1055 switch (up
->rpt_status
) {
1057 case TSIP_PARSED_DLE_1
:
1063 up
->rpt_status
= TSIP_PARSED_EMPTY
;
1067 up
->rpt_status
= TSIP_PARSED_DATA
;
1068 /* save packet ID */
1069 up
->rpt_buf
[0] = *c
;
1074 case TSIP_PARSED_DATA
:
1076 up
->rpt_status
= TSIP_PARSED_DLE_2
;
1078 mb(up
->rpt_cnt
++) = *c
;
1081 case TSIP_PARSED_DLE_2
:
1083 up
->rpt_status
= TSIP_PARSED_DATA
;
1088 up
->rpt_status
= TSIP_PARSED_FULL
;
1090 /* error: start new report packet */
1091 up
->rpt_status
= TSIP_PARSED_DLE_1
;
1092 up
->rpt_buf
[0] = *c
;
1096 case TSIP_PARSED_FULL
:
1097 case TSIP_PARSED_EMPTY
:
1100 up
->rpt_status
= TSIP_PARSED_EMPTY
;
1102 up
->rpt_status
= TSIP_PARSED_DLE_1
;
1108 if (up
->rpt_status
== TSIP_PARSED_DLE_1
) {
1110 if (pp
->sloppyclockflag
& CLK_FLAG2
)
1112 get_systime(&pp
->lastrec
);
1114 else if (up
->rpt_status
== TSIP_PARSED_EMPTY
)
1117 else if (up
->rpt_cnt
> BMAX
)
1118 up
->rpt_status
=TSIP_PARSED_EMPTY
;
1120 if (up
->rpt_status
== TSIP_PARSED_FULL
)
1121 palisade_receive(peer
);
1123 } /* while chars in buffer */
1128 * Trigger the Palisade's event input, which is driven off the RTS
1130 * Take a system time stamp to match the GPS time stamp.
1135 struct refclockproc
* pp
/* pointer to unit structure */
1138 int x
; /* state before & after RTS set */
1139 struct palisade_unit
*up
;
1141 up
= (struct palisade_unit
*) pp
->unitptr
;
1143 /* read the current status, so we put things back right */
1144 if (ioctl(pp
->io
.fd
, TIOCMGET
, &x
) < 0) {
1147 printf("Palisade HW_poll: unit %d: GET %s\n", up
->unit
, strerror(errno
));
1149 msyslog(LOG_ERR
, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
1154 x
|= TIOCM_RTS
; /* turn on RTS */
1157 if (up
->type
== CLK_ACUTIME
)
1158 write (pp
->io
.fd
, "", 1);
1160 if (ioctl(pp
->io
.fd
, TIOCMSET
, &x
) < 0) {
1163 printf("Palisade HW_poll: unit %d: SET \n", up
->unit
);
1166 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
1171 x
&= ~TIOCM_RTS
; /* turn off RTS */
1173 /* poll timestamp */
1174 get_systime(&pp
->lastrec
);
1176 if (ioctl(pp
->io
.fd
, TIOCMSET
, &x
) == -1) {
1179 printf("Palisade HW_poll: unit %d: UNSET \n", up
->unit
);
1182 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
1192 * this 'casts' a character array into a float
1200 #ifdef WORDS_BIGENDIAN
1201 ((char *) &sval
)[0] = *bp
++;
1202 ((char *) &sval
)[1] = *bp
++;
1203 ((char *) &sval
)[2] = *bp
++;
1204 ((char *) &sval
)[3] = *bp
++;
1206 ((char *) &sval
)[3] = *bp
++;
1207 ((char *) &sval
)[2] = *bp
++;
1208 ((char *) &sval
)[1] = *bp
++;
1209 ((char *) &sval
)[0] = *bp
;
1210 #endif /* ! XNTP_BIG_ENDIAN */
1216 * this 'casts' a character array into a double
1224 #ifdef WORDS_BIGENDIAN
1225 ((char *) &dval
)[0] = *bp
++;
1226 ((char *) &dval
)[1] = *bp
++;
1227 ((char *) &dval
)[2] = *bp
++;
1228 ((char *) &dval
)[3] = *bp
++;
1229 ((char *) &dval
)[4] = *bp
++;
1230 ((char *) &dval
)[5] = *bp
++;
1231 ((char *) &dval
)[6] = *bp
++;
1232 ((char *) &dval
)[7] = *bp
;
1234 ((char *) &dval
)[7] = *bp
++;
1235 ((char *) &dval
)[6] = *bp
++;
1236 ((char *) &dval
)[5] = *bp
++;
1237 ((char *) &dval
)[4] = *bp
++;
1238 ((char *) &dval
)[3] = *bp
++;
1239 ((char *) &dval
)[2] = *bp
++;
1240 ((char *) &dval
)[1] = *bp
++;
1241 ((char *) &dval
)[0] = *bp
;
1242 #endif /* ! XNTP_BIG_ENDIAN */
1247 * cast a 16 bit character array into a short (16 bit) int
1254 return (short) (bp
[1] + (bp
[0] << 8));
1258 * cast a 32 bit character array into a long (32 bit) int
1265 return (long) (bp
[0] << 24) |
1271 int refclock_palisade_bs
;
1272 #endif /* REFCLOCK */