/src/ntp-dev/ntpd/refclock_palisade.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
84 | | #ifdef DEBUG |
85 | | const char * Tracking_Status[15][15] = { |
86 | | { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" }, |
87 | | {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" }, |
88 | | { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" }, |
89 | | { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" }, |
90 | | { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } }; |
91 | | #endif |
92 | | |
93 | | /* |
94 | | * Transfer vector |
95 | | */ |
96 | | struct refclock refclock_palisade = { |
97 | | palisade_start, /* start up driver */ |
98 | | palisade_shutdown, /* shut down driver */ |
99 | | palisade_poll, /* transmit poll message */ |
100 | | noentry, /* not used */ |
101 | | noentry, /* initialize driver (not used) */ |
102 | | noentry, /* not used */ |
103 | | NOFLAGS /* not used */ |
104 | | }; |
105 | | |
106 | | static int decode_date(struct refclockproc *pp, const char *cp); |
107 | | |
108 | | /* Extract the clock type from the mode setting */ |
109 | 0 | #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F)) |
110 | | |
111 | | /* Supported clock types */ |
112 | 0 | #define CLK_TRIMBLE 0 /* Trimble Palisade */ |
113 | 0 | #define CLK_PRAECIS 1 /* Endrun Technologies Praecis */ |
114 | 0 | #define CLK_THUNDERBOLT 2 /* Trimble Thunderbolt GPS Receiver */ |
115 | 0 | #define CLK_ACUTIME 3 /* Trimble Acutime Gold */ |
116 | | #define CLK_ACUTIMEB 4 /* Trimble Actutime Gold Port B */ |
117 | | |
118 | | int praecis_msg; |
119 | | static void praecis_parse(struct recvbuf *rbufp, struct peer *peer); |
120 | | |
121 | | /* These routines are for sending packets to the Thunderbolt receiver |
122 | | * They are taken from Markus Prosch |
123 | | */ |
124 | | |
125 | | #ifdef PALISADE_SENDCMD_RESURRECTED |
126 | | /* |
127 | | * sendcmd - Build data packet for sending |
128 | | */ |
129 | | static void |
130 | | sendcmd ( |
131 | | struct packettx *buffer, |
132 | | int c |
133 | | ) |
134 | | { |
135 | | *buffer->data = DLE; |
136 | | *(buffer->data + 1) = (unsigned char)c; |
137 | | buffer->size = 2; |
138 | | } |
139 | | #endif /* PALISADE_SENDCMD_RESURRECTED */ |
140 | | |
141 | | /* |
142 | | * sendsupercmd - Build super data packet for sending |
143 | | */ |
144 | | static void |
145 | | sendsupercmd ( |
146 | | struct packettx *buffer, |
147 | | int c1, |
148 | | int c2 |
149 | | ) |
150 | 0 | { |
151 | 0 | *buffer->data = DLE; |
152 | 0 | *(buffer->data + 1) = (unsigned char)c1; |
153 | 0 | *(buffer->data + 2) = (unsigned char)c2; |
154 | 0 | buffer->size = 3; |
155 | 0 | } |
156 | | |
157 | | /* |
158 | | * sendbyte - |
159 | | */ |
160 | | static void |
161 | | sendbyte ( |
162 | | struct packettx *buffer, |
163 | | int b |
164 | | ) |
165 | 0 | { |
166 | 0 | if (b == DLE) |
167 | 0 | *(buffer->data+buffer->size++) = DLE; |
168 | 0 | *(buffer->data+buffer->size++) = (unsigned char)b; |
169 | 0 | } |
170 | | |
171 | | /* |
172 | | * sendint - |
173 | | */ |
174 | | static void |
175 | | sendint ( |
176 | | struct packettx *buffer, |
177 | | int a |
178 | | ) |
179 | 0 | { |
180 | 0 | sendbyte(buffer, (unsigned char)((a>>8) & 0xff)); |
181 | 0 | sendbyte(buffer, (unsigned char)(a & 0xff)); |
182 | 0 | } |
183 | | |
184 | | /* |
185 | | * sendetx - Send packet or super packet to the device |
186 | | */ |
187 | | static int |
188 | | sendetx ( |
189 | | struct packettx *buffer, |
190 | | int fd |
191 | | ) |
192 | 0 | { |
193 | 0 | int result; |
194 | | |
195 | 0 | *(buffer->data+buffer->size++) = DLE; |
196 | 0 | *(buffer->data+buffer->size++) = ETX; |
197 | 0 | result = write(fd, buffer->data, (unsigned long)buffer->size); |
198 | | |
199 | 0 | if (result != -1) |
200 | 0 | return (result); |
201 | 0 | else |
202 | 0 | return (-1); |
203 | 0 | } |
204 | | |
205 | | /* |
206 | | * init_thunderbolt - Prepares Thunderbolt receiver to be used with |
207 | | * NTP (also taken from Markus Prosch). |
208 | | */ |
209 | | static void |
210 | | init_thunderbolt ( |
211 | | int fd |
212 | | ) |
213 | 0 | { |
214 | 0 | struct packettx tx; |
215 | | |
216 | 0 | tx.size = 0; |
217 | 0 | tx.data = (u_char *) emalloc(100); |
218 | | |
219 | | /* set UTC time */ |
220 | 0 | sendsupercmd (&tx, 0x8E, 0xA2); |
221 | 0 | sendbyte (&tx, 0x3); |
222 | 0 | sendetx (&tx, fd); |
223 | | |
224 | | /* activate packets 0x8F-AB and 0x8F-AC */ |
225 | 0 | sendsupercmd (&tx, 0x8E, 0xA5); |
226 | 0 | sendint (&tx, 0x5); |
227 | 0 | sendetx (&tx, fd); |
228 | |
|
229 | 0 | free(tx.data); |
230 | 0 | } |
231 | | |
232 | | /* |
233 | | * init_acutime - Prepares Acutime Receiver to be used with NTP |
234 | | */ |
235 | | static void |
236 | | init_acutime ( |
237 | | int fd |
238 | | ) |
239 | 0 | { |
240 | | /* Disable all outputs, Enable Event-Polling on PortA so |
241 | | we can ask for time packets */ |
242 | 0 | struct packettx tx; |
243 | |
|
244 | 0 | tx.size = 0; |
245 | 0 | tx.data = (u_char *) emalloc(100); |
246 | |
|
247 | 0 | sendsupercmd(&tx, 0x8E, 0xA5); |
248 | 0 | sendbyte(&tx, 0x02); |
249 | 0 | sendbyte(&tx, 0x00); |
250 | 0 | sendbyte(&tx, 0x00); |
251 | 0 | sendbyte(&tx, 0x00); |
252 | 0 | sendetx(&tx, fd); |
253 | |
|
254 | 0 | free(tx.data); |
255 | 0 | } |
256 | | |
257 | | /* |
258 | | * palisade_start - open the devices and initialize data for processing |
259 | | */ |
260 | | static int |
261 | | palisade_start ( |
262 | | int unit, |
263 | | struct peer *peer |
264 | | ) |
265 | 0 | { |
266 | 0 | struct palisade_unit *up; |
267 | 0 | struct refclockproc *pp; |
268 | 0 | int fd; |
269 | 0 | char gpsdev[20]; |
270 | 0 | struct termios tio; |
271 | |
|
272 | 0 | snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit); |
273 | | |
274 | | /* |
275 | | * Open serial port. |
276 | | */ |
277 | 0 | fd = refclock_open(gpsdev, SPEED232, LDISC_RAW); |
278 | 0 | if (fd <= 0) { |
279 | 0 | #ifdef DEBUG |
280 | 0 | printf("Palisade(%d) start: open %s failed\n", unit, gpsdev); |
281 | 0 | #endif |
282 | 0 | return 0; |
283 | 0 | } |
284 | | |
285 | 0 | msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd, |
286 | 0 | gpsdev); |
287 | |
|
288 | 0 | if (tcgetattr(fd, &tio) < 0) { |
289 | 0 | msyslog(LOG_ERR, |
290 | 0 | "Palisade(%d) tcgetattr(fd, &tio): %m",unit); |
291 | 0 | #ifdef DEBUG |
292 | 0 | printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit); |
293 | 0 | #endif |
294 | 0 | close(fd); |
295 | 0 | return (0); |
296 | 0 | } |
297 | | |
298 | 0 | tio.c_cflag |= (PARENB|PARODD); |
299 | 0 | tio.c_iflag &= ~ICRNL; |
300 | | |
301 | | /* |
302 | | * Allocate and initialize unit structure |
303 | | */ |
304 | 0 | up = emalloc_zero(sizeof(*up)); |
305 | |
|
306 | 0 | up->type = CLK_TYPE(peer); |
307 | 0 | switch (up->type) { |
308 | 0 | case CLK_TRIMBLE: |
309 | | /* Normal mode, do nothing */ |
310 | 0 | break; |
311 | 0 | case CLK_PRAECIS: |
312 | 0 | msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled" |
313 | 0 | ,unit); |
314 | 0 | break; |
315 | 0 | case CLK_THUNDERBOLT: |
316 | 0 | msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled" |
317 | 0 | ,unit); |
318 | 0 | tio.c_cflag = (CS8|CLOCAL|CREAD); |
319 | 0 | break; |
320 | 0 | case CLK_ACUTIME: |
321 | 0 | msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled" |
322 | 0 | ,unit); |
323 | 0 | break; |
324 | 0 | default: |
325 | 0 | msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit); |
326 | 0 | break; |
327 | 0 | } |
328 | 0 | if (tcsetattr(fd, TCSANOW, &tio) == -1) { |
329 | 0 | msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit); |
330 | 0 | #ifdef DEBUG |
331 | 0 | printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit); |
332 | 0 | #endif |
333 | 0 | close(fd); |
334 | 0 | free(up); |
335 | 0 | return 0; |
336 | 0 | } |
337 | | |
338 | 0 | pp = peer->procptr; |
339 | 0 | pp->io.clock_recv = palisade_io; |
340 | 0 | pp->io.srcclock = peer; |
341 | 0 | pp->io.datalen = 0; |
342 | 0 | pp->io.fd = fd; |
343 | 0 | if (!io_addclock(&pp->io)) { |
344 | 0 | #ifdef DEBUG |
345 | 0 | printf("Palisade(%d) io_addclock\n",unit); |
346 | 0 | #endif |
347 | 0 | close(fd); |
348 | 0 | pp->io.fd = -1; |
349 | 0 | free(up); |
350 | 0 | return (0); |
351 | 0 | } |
352 | | |
353 | | /* |
354 | | * Initialize miscellaneous variables |
355 | | */ |
356 | 0 | pp->unitptr = up; |
357 | 0 | pp->clockdesc = DESCRIPTION; |
358 | |
|
359 | 0 | peer->precision = PRECISION; |
360 | 0 | peer->sstclktype = CTL_SST_TS_UHF; |
361 | 0 | peer->minpoll = TRMB_MINPOLL; |
362 | 0 | peer->maxpoll = TRMB_MAXPOLL; |
363 | 0 | memcpy((char *)&pp->refid, REFID, 4); |
364 | | |
365 | 0 | up->leap_status = 0; |
366 | 0 | up->unit = (short) unit; |
367 | 0 | up->rpt_status = TSIP_PARSED_EMPTY; |
368 | 0 | up->rpt_cnt = 0; |
369 | |
|
370 | 0 | if (up->type == CLK_THUNDERBOLT) |
371 | 0 | init_thunderbolt(fd); |
372 | 0 | if (up->type == CLK_ACUTIME) |
373 | 0 | init_acutime(fd); |
374 | |
|
375 | 0 | return 1; |
376 | 0 | } |
377 | | |
378 | | |
379 | | /* |
380 | | * palisade_shutdown - shut down the clock |
381 | | */ |
382 | | static void |
383 | | palisade_shutdown ( |
384 | | int unit, |
385 | | struct peer *peer |
386 | | ) |
387 | 0 | { |
388 | 0 | struct palisade_unit *up; |
389 | 0 | struct refclockproc *pp; |
390 | 0 | pp = peer->procptr; |
391 | 0 | up = pp->unitptr; |
392 | 0 | if (-1 != pp->io.fd) |
393 | 0 | io_closeclock(&pp->io); |
394 | 0 | if (NULL != up) |
395 | 0 | free(up); |
396 | 0 | } |
397 | | |
398 | | |
399 | | /* |
400 | | * unpack helpers |
401 | | */ |
402 | | |
403 | | static inline uint8_t |
404 | | get_u8( |
405 | | const char *cp) |
406 | 0 | { |
407 | 0 | return ((const u_char*)cp)[0]; |
408 | 0 | } |
409 | | |
410 | | static inline uint16_t |
411 | | get_u16( |
412 | | const char *cp) |
413 | 0 | { |
414 | 0 | return ((uint16_t)get_u8(cp) << 8) | get_u8(cp + 1); |
415 | 0 | } |
416 | | |
417 | | /* |
418 | | * unpack & fix date (the receiver provides a valid time for 1024 weeks |
419 | | * after 1997-12-14 and therefore folds back in 2017, 2037,...) |
420 | | * |
421 | | * Returns -1 on error, day-of-month + (month * 32) othertwise. |
422 | | */ |
423 | | int |
424 | | decode_date( |
425 | | struct refclockproc *pp, |
426 | | const char *cp) |
427 | 0 | { |
428 | 0 | static int32_t s_baseday = 0; |
429 | | |
430 | 0 | struct calendar jd; |
431 | 0 | int32_t rd; |
432 | |
|
433 | 0 | if (0 == s_baseday) { |
434 | 0 | if (!ntpcal_get_build_date(&jd)) { |
435 | 0 | jd.year = 2015; |
436 | 0 | jd.month = 1; |
437 | 0 | jd.monthday = 1; |
438 | 0 | } |
439 | 0 | s_baseday = ntpcal_date_to_rd(&jd); |
440 | 0 | } |
441 | | |
442 | | /* get date fields and convert to RDN */ |
443 | 0 | jd.monthday = get_u8 ( cp ); |
444 | 0 | jd.month = get_u8 (cp + 1); |
445 | 0 | jd.year = get_u16(cp + 2); |
446 | 0 | rd = ntpcal_date_to_rd(&jd); |
447 | | |
448 | | /* for the paranoid: do reverse calculation and cross-check */ |
449 | 0 | ntpcal_rd_to_date(&jd, rd); |
450 | 0 | if ((jd.monthday != get_u8 ( cp )) || |
451 | 0 | (jd.month != get_u8 (cp + 1)) || |
452 | 0 | (jd.year != get_u16(cp + 2)) ) |
453 | 0 | return - 1; |
454 | | |
455 | | /* calculate cycle shift to base day and calculate re-folded |
456 | | * date |
457 | | * |
458 | | * One could do a proper modulo calculation here, but a counting |
459 | | * loop is probably faster for the next few rollovers... |
460 | | */ |
461 | 0 | while (rd < s_baseday) |
462 | 0 | rd += 7*1024; |
463 | 0 | ntpcal_rd_to_date(&jd, rd); |
464 | | |
465 | | /* fill refclock structure & indicate success */ |
466 | 0 | pp->day = jd.yearday; |
467 | 0 | pp->year = jd.year; |
468 | 0 | return ((int)jd.month << 5) | jd.monthday; |
469 | 0 | } |
470 | | |
471 | | |
472 | | /* |
473 | | * TSIP_decode - decode the TSIP data packets |
474 | | */ |
475 | | int |
476 | | TSIP_decode ( |
477 | | struct peer *peer |
478 | | ) |
479 | 0 | { |
480 | 0 | int st; |
481 | 0 | long secint; |
482 | 0 | double secs; |
483 | 0 | double secfrac; |
484 | 0 | unsigned short event = 0; |
485 | 0 | int mmday; |
486 | | |
487 | 0 | struct palisade_unit *up; |
488 | 0 | struct refclockproc *pp; |
489 | |
|
490 | 0 | pp = peer->procptr; |
491 | 0 | up = pp->unitptr; |
492 | | |
493 | | /* |
494 | | * Check the time packet, decode its contents. |
495 | | * If the timecode has invalid length or is not in |
496 | | * proper format, declare bad format and exit. |
497 | | */ |
498 | |
|
499 | 0 | if ((up->type != CLK_THUNDERBOLT) & (up->type != CLK_ACUTIME)){ |
500 | 0 | if ((up->rpt_buf[0] == (char) 0x41) || |
501 | 0 | (up->rpt_buf[0] == (char) 0x46) || |
502 | 0 | (up->rpt_buf[0] == (char) 0x54) || |
503 | 0 | (up->rpt_buf[0] == (char) 0x4B) || |
504 | 0 | (up->rpt_buf[0] == (char) 0x6D)) { |
505 | | |
506 | | /* standard time packet - GPS time and GPS week number */ |
507 | 0 | #ifdef DEBUG |
508 | 0 | printf("Palisade Port B packets detected. Connect to Port A\n"); |
509 | 0 | #endif |
510 | |
|
511 | 0 | return 0; |
512 | 0 | } |
513 | 0 | } |
514 | | |
515 | | /* |
516 | | * We cast both to u_char to as 0x8f uses the sign bit on a char |
517 | | */ |
518 | 0 | if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) { |
519 | | /* |
520 | | * Superpackets |
521 | | */ |
522 | 0 | event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff); |
523 | 0 | if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) |
524 | | /* Ignore Packet */ |
525 | 0 | return 0; |
526 | | |
527 | 0 | switch (mb(0) & 0xff) { |
528 | 0 | int GPS_UTC_Offset; |
529 | 0 | long tow; |
530 | | |
531 | 0 | case PACKET_8F0B: |
532 | |
|
533 | 0 | if (up->polled <= 0) |
534 | 0 | return 0; |
535 | | |
536 | 0 | if (up->rpt_cnt != LENCODE_8F0B) /* check length */ |
537 | 0 | break; |
538 | | |
539 | 0 | #ifdef DEBUG |
540 | 0 | if (debug > 1) { |
541 | 0 | int ts; |
542 | 0 | double lat, lon, alt; |
543 | 0 | lat = getdbl((u_char *) &mb(42)) * R2D; |
544 | 0 | lon = getdbl((u_char *) &mb(50)) * R2D; |
545 | 0 | alt = getdbl((u_char *) &mb(58)); |
546 | |
|
547 | 0 | printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", |
548 | 0 | up->unit, lat,lon,alt); |
549 | 0 | printf("TSIP_decode: unit %d: Sats:", |
550 | 0 | up->unit); |
551 | 0 | for (st = 66, ts = 0; st <= 73; st++) |
552 | 0 | if (mb(st)) { |
553 | 0 | if (mb(st) > 0) ts++; |
554 | 0 | printf(" %02d", mb(st)); |
555 | 0 | } |
556 | 0 | printf(" : Tracking %d\n", ts); |
557 | 0 | } |
558 | 0 | #endif |
559 | |
|
560 | 0 | GPS_UTC_Offset = getint((u_char *) &mb(16)); |
561 | 0 | if (GPS_UTC_Offset == 0) { /* Check UTC offset */ |
562 | 0 | #ifdef DEBUG |
563 | 0 | printf("TSIP_decode: UTC Offset Unknown\n"); |
564 | 0 | #endif |
565 | 0 | break; |
566 | 0 | } |
567 | | |
568 | 0 | secs = getdbl((u_char *) &mb(3)); |
569 | 0 | secint = (long) secs; |
570 | 0 | secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */ |
571 | |
|
572 | 0 | pp->nsec = (long) (secfrac * 1000000000); |
573 | |
|
574 | 0 | secint %= 86400; /* Only care about today */ |
575 | 0 | pp->hour = secint / 3600; |
576 | 0 | secint %= 3600; |
577 | 0 | pp->minute = secint / 60; |
578 | 0 | secint %= 60; |
579 | 0 | pp->second = secint % 60; |
580 | |
|
581 | 0 | mmday = decode_date(pp, &mb(11)); |
582 | 0 | if (mmday < 0) |
583 | 0 | break; |
584 | | |
585 | 0 | #ifdef DEBUG |
586 | 0 | if (debug > 1) |
587 | 0 | printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n", |
588 | 0 | up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, |
589 | 0 | pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, GPS_UTC_Offset); |
590 | 0 | #endif |
591 | | /* Only use this packet when no |
592 | | * 8F-AD's are being received |
593 | | */ |
594 | |
|
595 | 0 | if (up->leap_status) { |
596 | 0 | up->leap_status = 0; |
597 | 0 | return 0; |
598 | 0 | } |
599 | | |
600 | 0 | return 2; |
601 | 0 | break; |
602 | | |
603 | 0 | case PACKET_NTP: |
604 | | /* Palisade-NTP Packet */ |
605 | |
|
606 | 0 | if (up->rpt_cnt != LENCODE_NTP) /* check length */ |
607 | 0 | break; |
608 | | |
609 | 0 | up->leap_status = mb(19); |
610 | |
|
611 | 0 | if (up->polled <= 0) |
612 | 0 | return 0; |
613 | | |
614 | | /* Check Tracking Status */ |
615 | 0 | st = mb(18); |
616 | 0 | if (st < 0 || st > 14) |
617 | 0 | st = 14; |
618 | 0 | if ((st >= 2 && st <= 7) || st == 11 || st == 12) { |
619 | 0 | #ifdef DEBUG |
620 | 0 | printf("TSIP_decode: Not Tracking Sats : %s\n", |
621 | 0 | *Tracking_Status[st]); |
622 | 0 | #endif |
623 | 0 | refclock_report(peer, CEVNT_BADTIME); |
624 | 0 | up->polled = -1; |
625 | 0 | return 0; |
626 | 0 | break; |
627 | 0 | } |
628 | | |
629 | 0 | mmday = decode_date(pp, &mb(14)); |
630 | 0 | if (mmday < 0) |
631 | 0 | break; |
632 | 0 | up->month = (mmday >> 5); /* Save for LEAP check */ |
633 | |
|
634 | 0 | if ( (up->leap_status & PALISADE_LEAP_PENDING) && |
635 | | /* Avoid early announce: https://bugs.ntp.org/2773 */ |
636 | 0 | (6 == up->month || 12 == up->month) ) { |
637 | 0 | if (up->leap_status & PALISADE_UTC_TIME) |
638 | 0 | pp->leap = LEAP_ADDSECOND; |
639 | 0 | else |
640 | 0 | pp->leap = LEAP_DELSECOND; |
641 | 0 | } |
642 | 0 | else if (up->leap_status) |
643 | 0 | pp->leap = LEAP_NOWARNING; |
644 | | |
645 | 0 | else { /* UTC flag is not set: |
646 | | * Receiver may have been reset, and lost |
647 | | * its UTC almanac data */ |
648 | 0 | pp->leap = LEAP_NOTINSYNC; |
649 | 0 | #ifdef DEBUG |
650 | 0 | printf("TSIP_decode: UTC Almanac unavailable: %d\n", |
651 | 0 | mb(19)); |
652 | 0 | #endif |
653 | 0 | refclock_report(peer, CEVNT_BADTIME); |
654 | 0 | up->polled = -1; |
655 | 0 | return 0; |
656 | 0 | } |
657 | | |
658 | 0 | pp->nsec = (long) (getdbl((u_char *) &mb(3)) |
659 | 0 | * 1000000000); |
660 | |
|
661 | 0 | pp->hour = mb(11); |
662 | 0 | pp->minute = mb(12); |
663 | 0 | pp->second = mb(13); |
664 | |
|
665 | 0 | #ifdef DEBUG |
666 | 0 | if (debug > 1) |
667 | 0 | printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n", |
668 | 0 | up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, |
669 | 0 | pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, |
670 | 0 | mb(19), *Tracking_Status[st]); |
671 | 0 | #endif |
672 | 0 | return 1; |
673 | 0 | break; |
674 | | |
675 | 0 | case PACKET_8FAC: |
676 | 0 | if (up->polled <= 0) |
677 | 0 | return 0; |
678 | | |
679 | 0 | if (up->rpt_cnt != LENCODE_8FAC)/* check length */ |
680 | 0 | break; |
681 | | |
682 | 0 | #ifdef DEBUG |
683 | 0 | if (debug > 1) { |
684 | 0 | double lat, lon, alt; |
685 | 0 | lat = getdbl((u_char *) &mb(36)) * R2D; |
686 | 0 | lon = getdbl((u_char *) &mb(44)) * R2D; |
687 | 0 | alt = getdbl((u_char *) &mb(52)); |
688 | |
|
689 | 0 | printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", |
690 | 0 | up->unit, lat,lon,alt); |
691 | 0 | printf("TSIP_decode: unit %d\n", up->unit); |
692 | 0 | } |
693 | 0 | #endif |
694 | 0 | if ( (getint((u_char *) &mb(10)) & 0x80) && |
695 | | /* Avoid early announce: https://bugs.ntp.org/2773 */ |
696 | 0 | (6 == up->month || 12 == up->month) ) |
697 | 0 | pp->leap = LEAP_ADDSECOND; /* we ASSUME addsecond */ |
698 | 0 | else |
699 | 0 | pp->leap = LEAP_NOWARNING; |
700 | |
|
701 | 0 | #ifdef DEBUG |
702 | 0 | if (debug > 1) |
703 | 0 | printf("TSIP_decode: unit %d: 0x%02x leap %d\n", |
704 | 0 | up->unit, mb(0) & 0xff, pp->leap); |
705 | 0 | if (debug > 1) { |
706 | 0 | printf("Receiver MODE: 0x%02X\n", (u_char)mb(1)); |
707 | 0 | if (mb(1) == 0x00) |
708 | 0 | printf(" AUTOMATIC\n"); |
709 | 0 | if (mb(1) == 0x01) |
710 | 0 | printf(" SINGLE SATELLITE\n"); |
711 | 0 | if (mb(1) == 0x03) |
712 | 0 | printf(" HORIZONTAL(2D)\n"); |
713 | 0 | if (mb(1) == 0x04) |
714 | 0 | printf(" FULL POSITION(3D)\n"); |
715 | 0 | if (mb(1) == 0x05) |
716 | 0 | printf(" DGPR REFERENCE\n"); |
717 | 0 | if (mb(1) == 0x06) |
718 | 0 | printf(" CLOCK HOLD(2D)\n"); |
719 | 0 | if (mb(1) == 0x07) |
720 | 0 | printf(" OVERDETERMINED CLOCK\n"); |
721 | |
|
722 | 0 | printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2)); |
723 | 0 | if (mb(2) == 0x00) |
724 | 0 | printf(" NORMAL\n"); |
725 | 0 | if (mb(2) == 0x01) |
726 | 0 | printf(" POWER-UP\n"); |
727 | 0 | if (mb(2) == 0x02) |
728 | 0 | printf(" AUTO HOLDOVER\n"); |
729 | 0 | if (mb(2) == 0x03) |
730 | 0 | printf(" MANUAL HOLDOVER\n"); |
731 | 0 | if (mb(2) == 0x04) |
732 | 0 | printf(" RECOVERY\n"); |
733 | 0 | if (mb(2) == 0x06) |
734 | 0 | printf(" DISCIPLINING DISABLED\n"); |
735 | 0 | } |
736 | 0 | #endif |
737 | 0 | return 0; |
738 | 0 | break; |
739 | | |
740 | 0 | case PACKET_8FAB: |
741 | | /* Thunderbolt Primary Timing Packet */ |
742 | |
|
743 | 0 | if (up->rpt_cnt != LENCODE_8FAB) /* check length */ |
744 | 0 | break; |
745 | | |
746 | 0 | if (up->polled <= 0) |
747 | 0 | return 0; |
748 | | |
749 | 0 | GPS_UTC_Offset = getint((u_char *) &mb(7)); |
750 | |
|
751 | 0 | if (GPS_UTC_Offset == 0){ /* Check UTC Offset */ |
752 | 0 | #ifdef DEBUG |
753 | 0 | printf("TSIP_decode: UTC Offset Unknown\n"); |
754 | 0 | #endif |
755 | 0 | break; |
756 | 0 | } |
757 | | |
758 | | |
759 | 0 | if ((mb(9) & 0x1d) == 0x0) { |
760 | | /* if we know the GPS time and the UTC offset, |
761 | | we expect UTC timing information !!! */ |
762 | |
|
763 | 0 | pp->leap = LEAP_NOTINSYNC; |
764 | 0 | refclock_report(peer, CEVNT_BADTIME); |
765 | 0 | up->polled = -1; |
766 | 0 | return 0; |
767 | 0 | } |
768 | | |
769 | 0 | pp->nsec = 0; |
770 | 0 | #ifdef DEBUG |
771 | 0 | printf("\nTiming Flags are:\n"); |
772 | 0 | printf("Timing flag value is: 0x%X\n", mb(9)); |
773 | 0 | if ((mb(9) & 0x01) != 0) |
774 | 0 | printf (" Getting UTC time\n"); |
775 | 0 | else |
776 | 0 | printf (" Getting GPS time\n"); |
777 | 0 | if ((mb(9) & 0x02) != 0) |
778 | 0 | printf (" PPS is from UTC\n"); |
779 | 0 | else |
780 | 0 | printf (" PPS is from GPS\n"); |
781 | 0 | if ((mb(9) & 0x04) != 0) |
782 | 0 | printf (" Time is not Set\n"); |
783 | 0 | else |
784 | 0 | printf (" Time is Set\n"); |
785 | 0 | if ((mb(9) & 0x08) != 0) |
786 | 0 | printf(" I dont have UTC info\n"); |
787 | 0 | else |
788 | 0 | printf (" I have UTC info\n"); |
789 | 0 | if ((mb(9) & 0x10) != 0) |
790 | 0 | printf (" Time is from USER\n\n"); |
791 | 0 | else |
792 | 0 | printf (" Time is from GPS\n\n"); |
793 | 0 | #endif |
794 | |
|
795 | 0 | mmday = decode_date(pp, &mb(13)); |
796 | 0 | if (mmday < 0) |
797 | 0 | break; |
798 | 0 | tow = getlong((u_char *) &mb(1)); |
799 | 0 | #ifdef DEBUG |
800 | 0 | if (debug > 1) { |
801 | 0 | printf("pp->day: %d\n", pp->day); |
802 | 0 | printf("TOW: %ld\n", tow); |
803 | 0 | printf("DAY: %d\n", (mmday & 31)); |
804 | 0 | } |
805 | 0 | #endif |
806 | 0 | pp->hour = mb(12); |
807 | 0 | pp->minute = mb(11); |
808 | 0 | pp->second = mb(10); |
809 | | |
810 | |
|
811 | 0 | #ifdef DEBUG |
812 | 0 | if (debug > 1) |
813 | 0 | printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ", |
814 | 0 | up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, |
815 | 0 | pp->nsec, (mmday >> 5), (mmday & 31), pp->year); |
816 | 0 | #endif |
817 | 0 | return 1; |
818 | 0 | break; |
819 | | |
820 | 0 | default: |
821 | | /* Ignore Packet */ |
822 | 0 | return 0; |
823 | 0 | } /* switch */ |
824 | 0 | } /* if 8F packets */ |
825 | | |
826 | 0 | else if (up->rpt_buf[0] == (u_char)0x42) { |
827 | 0 | printf("0x42\n"); |
828 | 0 | return 0; |
829 | 0 | } |
830 | 0 | else if (up->rpt_buf[0] == (u_char)0x43) { |
831 | 0 | printf("0x43\n"); |
832 | 0 | return 0; |
833 | 0 | } |
834 | 0 | else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){ |
835 | 0 | printf("Undocumented 0x41 packet on Thunderbolt\n"); |
836 | 0 | return 0; |
837 | 0 | } |
838 | 0 | else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) { |
839 | 0 | #ifdef DEBUG |
840 | 0 | printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0))); |
841 | 0 | printf("GPS WN: %d\n", getint((u_char *) &mb(4))); |
842 | 0 | printf("GPS UTC-GPS Offser: %ld\n", (long)getlong((u_char *) &mb(6))); |
843 | 0 | #endif |
844 | 0 | return 0; |
845 | 0 | } |
846 | | |
847 | | /* Health Status for Acutime Receiver */ |
848 | 0 | else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) { |
849 | 0 | #ifdef DEBUG |
850 | 0 | if (debug > 1) |
851 | | /* Status Codes */ |
852 | 0 | switch (mb(0)) { |
853 | 0 | case 0x00: |
854 | 0 | printf ("Doing Position Fixes\n"); |
855 | 0 | break; |
856 | 0 | case 0x01: |
857 | 0 | printf ("Do no have GPS time yet\n"); |
858 | 0 | break; |
859 | 0 | case 0x03: |
860 | 0 | printf ("PDOP is too high\n"); |
861 | 0 | break; |
862 | 0 | case 0x08: |
863 | 0 | printf ("No usable satellites\n"); |
864 | 0 | break; |
865 | 0 | case 0x09: |
866 | 0 | printf ("Only 1 usable satellite\n"); |
867 | 0 | break; |
868 | 0 | case 0x0A: |
869 | 0 | printf ("Only 2 usable satellites\n"); |
870 | 0 | break; |
871 | 0 | case 0x0B: |
872 | 0 | printf ("Only 3 usable satellites\n"); |
873 | 0 | break; |
874 | 0 | case 0x0C: |
875 | 0 | printf("The Chosen satellite is unusable\n"); |
876 | 0 | break; |
877 | 0 | } |
878 | 0 | #endif |
879 | | /* Error Codes */ |
880 | 0 | if (mb(1) != 0) { |
881 | | |
882 | 0 | refclock_report(peer, CEVNT_BADTIME); |
883 | 0 | up->polled = -1; |
884 | 0 | #ifdef DEBUG |
885 | 0 | if (debug > 1) { |
886 | 0 | if (mb(1) & 0x01) |
887 | 0 | printf ("Signal Processor Error, reset unit.\n"); |
888 | 0 | if (mb(1) & 0x02) |
889 | 0 | printf ("Alignment error, channel or chip 1, reset unit.\n"); |
890 | 0 | if (mb(1) & 0x03) |
891 | 0 | printf ("Alignment error, channel or chip 2, reset unit.\n"); |
892 | 0 | if (mb(1) & 0x04) |
893 | 0 | printf ("Antenna feed line fault (open or short)\n"); |
894 | 0 | if (mb(1) & 0x05) |
895 | 0 | printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n"); |
896 | 0 | } |
897 | 0 | #endif |
898 | | |
899 | 0 | return 0; |
900 | 0 | } |
901 | 0 | } |
902 | 0 | else if (up->rpt_buf[0] == 0x54) |
903 | 0 | return 0; |
904 | | |
905 | 0 | else if (up->rpt_buf[0] == PACKET_6D) { |
906 | 0 | #ifdef DEBUG |
907 | 0 | int sats; |
908 | |
|
909 | 0 | if ((mb(0) & 0x01) && (mb(0) & 0x02)) |
910 | 0 | printf("2d Fix Dimension\n"); |
911 | 0 | if (mb(0) & 0x04) |
912 | 0 | printf("3d Fix Dimension\n"); |
913 | |
|
914 | 0 | if (mb(0) & 0x08) |
915 | 0 | printf("Fix Mode is MANUAL\n"); |
916 | 0 | else |
917 | 0 | printf("Fix Mode is AUTO\n"); |
918 | | |
919 | 0 | sats = mb(0) & 0xF0; |
920 | 0 | sats = sats >> 4; |
921 | 0 | printf("Tracking %d Satellites\n", sats); |
922 | 0 | #endif |
923 | 0 | return 0; |
924 | 0 | } /* else if not super packet */ |
925 | 0 | refclock_report(peer, CEVNT_BADREPLY); |
926 | 0 | up->polled = -1; |
927 | 0 | #ifdef DEBUG |
928 | 0 | printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", |
929 | 0 | up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, |
930 | 0 | event, up->rpt_cnt); |
931 | 0 | #endif |
932 | 0 | return 0; |
933 | 0 | } |
934 | | |
935 | | /* |
936 | | * palisade__receive - receive data from the serial interface |
937 | | */ |
938 | | |
939 | | static void |
940 | | palisade_receive ( |
941 | | struct peer * peer |
942 | | ) |
943 | 0 | { |
944 | 0 | struct palisade_unit *up; |
945 | 0 | struct refclockproc *pp; |
946 | | |
947 | | /* |
948 | | * Initialize pointers and read the timecode and timestamp. |
949 | | */ |
950 | 0 | pp = peer->procptr; |
951 | 0 | up = pp->unitptr; |
952 | | |
953 | 0 | if (! TSIP_decode(peer)) return; |
954 | | |
955 | 0 | if (up->polled <= 0) |
956 | 0 | return; /* no poll pending, already received or timeout */ |
957 | | |
958 | 0 | up->polled = 0; /* Poll reply received */ |
959 | 0 | pp->lencode = 0; /* clear time code */ |
960 | 0 | #ifdef DEBUG |
961 | 0 | if (debug) |
962 | 0 | printf( |
963 | 0 | "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n", |
964 | 0 | up->unit, pp->year, pp->day, pp->hour, pp->minute, |
965 | 0 | pp->second, pp->nsec); |
966 | 0 | #endif |
967 | | |
968 | | /* |
969 | | * Process the sample |
970 | | * Generate timecode: YYYY DoY HH:MM:SS.microsec |
971 | | * report and process |
972 | | */ |
973 | |
|
974 | 0 | snprintf(pp->a_lastcode, sizeof(pp->a_lastcode), |
975 | 0 | "%4d %03d %02d:%02d:%02d.%09ld", |
976 | 0 | pp->year, pp->day, |
977 | 0 | pp->hour,pp->minute, pp->second, pp->nsec); |
978 | 0 | pp->lencode = 24; |
979 | |
|
980 | 0 | if (!refclock_process(pp)) { |
981 | 0 | refclock_report(peer, CEVNT_BADTIME); |
982 | |
|
983 | 0 | #ifdef DEBUG |
984 | 0 | printf("palisade_receive: unit %d: refclock_process failed!\n", |
985 | 0 | up->unit); |
986 | 0 | #endif |
987 | 0 | return; |
988 | 0 | } |
989 | | |
990 | 0 | record_clock_stats(&peer->srcadr, pp->a_lastcode); |
991 | |
|
992 | 0 | #ifdef DEBUG |
993 | 0 | if (debug) |
994 | 0 | printf("palisade_receive: unit %d: %s\n", |
995 | 0 | up->unit, prettydate(&pp->lastrec)); |
996 | 0 | #endif |
997 | 0 | pp->lastref = pp->lastrec; |
998 | 0 | refclock_receive(peer); |
999 | 0 | } |
1000 | | |
1001 | | |
1002 | | /* |
1003 | | * palisade_poll - called by the transmit procedure |
1004 | | * |
1005 | | */ |
1006 | | static void |
1007 | | palisade_poll ( |
1008 | | int unit, |
1009 | | struct peer *peer |
1010 | | ) |
1011 | 0 | { |
1012 | 0 | struct palisade_unit *up; |
1013 | 0 | struct refclockproc *pp; |
1014 | | |
1015 | 0 | pp = peer->procptr; |
1016 | 0 | up = pp->unitptr; |
1017 | |
|
1018 | 0 | pp->polls++; |
1019 | 0 | if (up->polled > 0) /* last reply never arrived or error */ |
1020 | 0 | refclock_report(peer, CEVNT_TIMEOUT); |
1021 | |
|
1022 | 0 | up->polled = 2; /* synchronous packet + 1 event */ |
1023 | | |
1024 | 0 | #ifdef DEBUG |
1025 | 0 | if (debug) |
1026 | 0 | printf("palisade_poll: unit %d: polling %s\n", unit, |
1027 | 0 | (pp->sloppyclockflag & CLK_FLAG2) ? |
1028 | 0 | "synchronous packet" : "event"); |
1029 | 0 | #endif |
1030 | |
|
1031 | 0 | if (pp->sloppyclockflag & CLK_FLAG2) |
1032 | 0 | return; /* using synchronous packet input */ |
1033 | | |
1034 | 0 | if(up->type == CLK_PRAECIS) { |
1035 | 0 | if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) |
1036 | 0 | msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit); |
1037 | 0 | else { |
1038 | 0 | praecis_msg = 1; |
1039 | 0 | return; |
1040 | 0 | } |
1041 | 0 | } |
1042 | | |
1043 | 0 | if (HW_poll(pp) < 0) |
1044 | 0 | refclock_report(peer, CEVNT_FAULT); |
1045 | 0 | } |
1046 | | |
1047 | | static void |
1048 | | praecis_parse ( |
1049 | | struct recvbuf *rbufp, |
1050 | | struct peer *peer |
1051 | | ) |
1052 | 0 | { |
1053 | 0 | static char buf[100]; |
1054 | 0 | static int p = 0; |
1055 | 0 | struct refclockproc *pp; |
1056 | |
|
1057 | 0 | pp = peer->procptr; |
1058 | |
|
1059 | 0 | memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length); |
1060 | 0 | p += rbufp->recv_length; |
1061 | |
|
1062 | 0 | if(buf[p-2] == '\r' && buf[p-1] == '\n') { |
1063 | 0 | buf[p-2] = '\0'; |
1064 | 0 | record_clock_stats(&peer->srcadr, buf); |
1065 | |
|
1066 | 0 | p = 0; |
1067 | 0 | praecis_msg = 0; |
1068 | |
|
1069 | 0 | if (HW_poll(pp) < 0) |
1070 | 0 | refclock_report(peer, CEVNT_FAULT); |
1071 | |
|
1072 | 0 | } |
1073 | 0 | } |
1074 | | |
1075 | | static void |
1076 | | palisade_io ( |
1077 | | struct recvbuf *rbufp |
1078 | | ) |
1079 | 0 | { |
1080 | | /* |
1081 | | * Initialize pointers and read the timecode and timestamp. |
1082 | | */ |
1083 | 0 | struct palisade_unit *up; |
1084 | 0 | struct refclockproc *pp; |
1085 | 0 | struct peer *peer; |
1086 | |
|
1087 | 0 | char * c, * d; |
1088 | |
|
1089 | 0 | peer = rbufp->recv_peer; |
1090 | 0 | pp = peer->procptr; |
1091 | 0 | up = pp->unitptr; |
1092 | |
|
1093 | 0 | if(up->type == CLK_PRAECIS) { |
1094 | 0 | if(praecis_msg) { |
1095 | 0 | praecis_parse(rbufp,peer); |
1096 | 0 | return; |
1097 | 0 | } |
1098 | 0 | } |
1099 | | |
1100 | 0 | c = (char *) &rbufp->recv_space; |
1101 | 0 | d = c + rbufp->recv_length; |
1102 | | |
1103 | 0 | while (c != d) { |
1104 | | |
1105 | | /* Build time packet */ |
1106 | 0 | switch (up->rpt_status) { |
1107 | | |
1108 | 0 | case TSIP_PARSED_DLE_1: |
1109 | 0 | switch (*c) |
1110 | 0 | { |
1111 | 0 | case 0: |
1112 | 0 | case DLE: |
1113 | 0 | case ETX: |
1114 | 0 | up->rpt_status = TSIP_PARSED_EMPTY; |
1115 | 0 | break; |
1116 | | |
1117 | 0 | default: |
1118 | 0 | up->rpt_status = TSIP_PARSED_DATA; |
1119 | | /* save packet ID */ |
1120 | 0 | up->rpt_buf[0] = *c; |
1121 | 0 | break; |
1122 | 0 | } |
1123 | 0 | break; |
1124 | | |
1125 | 0 | case TSIP_PARSED_DATA: |
1126 | 0 | if (*c == DLE) |
1127 | 0 | up->rpt_status = TSIP_PARSED_DLE_2; |
1128 | 0 | else |
1129 | 0 | mb(up->rpt_cnt++) = *c; |
1130 | 0 | break; |
1131 | | |
1132 | 0 | case TSIP_PARSED_DLE_2: |
1133 | 0 | if (*c == DLE) { |
1134 | 0 | up->rpt_status = TSIP_PARSED_DATA; |
1135 | 0 | mb(up->rpt_cnt++) = |
1136 | 0 | *c; |
1137 | 0 | } |
1138 | 0 | else if (*c == ETX) |
1139 | 0 | up->rpt_status = TSIP_PARSED_FULL; |
1140 | 0 | else { |
1141 | | /* error: start new report packet */ |
1142 | 0 | up->rpt_status = TSIP_PARSED_DLE_1; |
1143 | 0 | up->rpt_buf[0] = *c; |
1144 | 0 | } |
1145 | 0 | break; |
1146 | | |
1147 | 0 | case TSIP_PARSED_FULL: |
1148 | 0 | case TSIP_PARSED_EMPTY: |
1149 | 0 | default: |
1150 | 0 | if ( *c != DLE) |
1151 | 0 | up->rpt_status = TSIP_PARSED_EMPTY; |
1152 | 0 | else |
1153 | 0 | up->rpt_status = TSIP_PARSED_DLE_1; |
1154 | 0 | break; |
1155 | 0 | } |
1156 | | |
1157 | 0 | c++; |
1158 | |
|
1159 | 0 | if (up->rpt_status == TSIP_PARSED_DLE_1) { |
1160 | 0 | up->rpt_cnt = 0; |
1161 | 0 | if (pp->sloppyclockflag & CLK_FLAG2) |
1162 | | /* stamp it */ |
1163 | 0 | get_systime(&pp->lastrec); |
1164 | 0 | } |
1165 | 0 | else if (up->rpt_status == TSIP_PARSED_EMPTY) |
1166 | 0 | up->rpt_cnt = 0; |
1167 | | |
1168 | 0 | else if (up->rpt_cnt > BMAX) |
1169 | 0 | up->rpt_status =TSIP_PARSED_EMPTY; |
1170 | |
|
1171 | 0 | if (up->rpt_status == TSIP_PARSED_FULL) |
1172 | 0 | palisade_receive(peer); |
1173 | |
|
1174 | 0 | } /* while chars in buffer */ |
1175 | 0 | } |
1176 | | |
1177 | | |
1178 | | /* |
1179 | | * Trigger the Palisade's event input, which is driven off the RTS |
1180 | | * |
1181 | | * Take a system time stamp to match the GPS time stamp. |
1182 | | * |
1183 | | */ |
1184 | | long |
1185 | | HW_poll ( |
1186 | | struct refclockproc * pp /* pointer to unit structure */ |
1187 | | ) |
1188 | 0 | { |
1189 | 0 | int x; /* state before & after RTS set */ |
1190 | 0 | struct palisade_unit *up; |
1191 | |
|
1192 | 0 | up = pp->unitptr; |
1193 | | |
1194 | | /* read the current status, so we put things back right */ |
1195 | 0 | if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { |
1196 | 0 | DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n", |
1197 | 0 | up->unit)); |
1198 | 0 | msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", |
1199 | 0 | up->unit); |
1200 | 0 | return -1; |
1201 | 0 | } |
1202 | | |
1203 | 0 | x |= TIOCM_RTS; /* turn on RTS */ |
1204 | | |
1205 | | /* Edge trigger */ |
1206 | 0 | if (up->type == CLK_ACUTIME) |
1207 | 0 | write (pp->io.fd, "", 1); |
1208 | | |
1209 | 0 | if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { |
1210 | 0 | #ifdef DEBUG |
1211 | 0 | if (debug) |
1212 | 0 | printf("Palisade HW_poll: unit %d: SET \n", up->unit); |
1213 | 0 | #endif |
1214 | 0 | msyslog(LOG_ERR, |
1215 | 0 | "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", |
1216 | 0 | up->unit); |
1217 | 0 | return -1; |
1218 | 0 | } |
1219 | | |
1220 | 0 | x &= ~TIOCM_RTS; /* turn off RTS */ |
1221 | | |
1222 | | /* poll timestamp */ |
1223 | 0 | get_systime(&pp->lastrec); |
1224 | |
|
1225 | 0 | if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { |
1226 | 0 | #ifdef DEBUG |
1227 | 0 | if (debug) |
1228 | 0 | printf("Palisade HW_poll: unit %d: UNSET \n", up->unit); |
1229 | 0 | #endif |
1230 | 0 | msyslog(LOG_ERR, |
1231 | 0 | "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", |
1232 | 0 | up->unit); |
1233 | 0 | return -1; |
1234 | 0 | } |
1235 | | |
1236 | 0 | return 0; |
1237 | 0 | } |
1238 | | |
1239 | | /* |
1240 | | * copy/swap a big-endian palisade double into a host double |
1241 | | */ |
1242 | | static double |
1243 | | getdbl ( |
1244 | | u_char *bp |
1245 | | ) |
1246 | 0 | { |
1247 | | #ifdef WORDS_BIGENDIAN |
1248 | | double out; |
1249 | | |
1250 | | memcpy(&out, bp, sizeof(out)); |
1251 | | return out; |
1252 | | #else |
1253 | 0 | union { |
1254 | 0 | u_char ch[8]; |
1255 | 0 | u_int32 u32[2]; |
1256 | 0 | } ui; |
1257 | | |
1258 | 0 | union { |
1259 | 0 | double out; |
1260 | 0 | u_int32 u32[2]; |
1261 | 0 | } uo; |
1262 | |
|
1263 | 0 | memcpy(ui.ch, bp, sizeof(ui.ch)); |
1264 | | /* least-significant 32 bits of double from swapped bp[4] to bp[7] */ |
1265 | 0 | uo.u32[0] = ntohl(ui.u32[1]); |
1266 | | /* most-significant 32 bits from swapped bp[0] to bp[3] */ |
1267 | 0 | uo.u32[1] = ntohl(ui.u32[0]); |
1268 | |
|
1269 | 0 | return uo.out; |
1270 | 0 | #endif |
1271 | 0 | } |
1272 | | |
1273 | | /* |
1274 | | * copy/swap a big-endian palisade short into a host short |
1275 | | */ |
1276 | | static short |
1277 | | getint ( |
1278 | | u_char *bp |
1279 | | ) |
1280 | 0 | { |
1281 | 0 | u_short us; |
1282 | |
|
1283 | 0 | memcpy(&us, bp, sizeof(us)); |
1284 | 0 | return (short)ntohs(us); |
1285 | 0 | } |
1286 | | |
1287 | | /* |
1288 | | * copy/swap a big-endian palisade 32-bit int into a host 32-bit int |
1289 | | */ |
1290 | | static int32 |
1291 | | getlong( |
1292 | | u_char *bp |
1293 | | ) |
1294 | 0 | { |
1295 | 0 | u_int32 u32; |
1296 | |
|
1297 | 0 | memcpy(&u32, bp, sizeof(u32)); |
1298 | 0 | return (int32)(u_int32)ntohl(u32); |
1299 | 0 | } |
1300 | | |
1301 | | #else /* REFCLOCK && CLOCK_PALISADE*/ |
1302 | | int refclock_palisade_c_notempty; |
1303 | | #endif |