Thu Sep 3 07:26:41 2020 UTC ()
remove unneeded newline in quotes variable string - keeps ntpq happy


(kardel)
diff -r1.22 -r1.23 src/external/bsd/ntp/dist/ntpd/refclock_parse.c

cvs diff -r1.22 -r1.23 src/external/bsd/ntp/dist/ntpd/refclock_parse.c (switch to unified diff)

--- src/external/bsd/ntp/dist/ntpd/refclock_parse.c 2020/05/25 20:47:25 1.22
+++ src/external/bsd/ntp/dist/ntpd/refclock_parse.c 2020/09/03 07:26:41 1.23
@@ -1,1000 +1,1000 @@ @@ -1,1000 +1,1000 @@
1/* $NetBSD: refclock_parse.c,v 1.22 2020/05/25 20:47:25 christos Exp $ */ 1/* $NetBSD: refclock_parse.c,v 1.23 2020/09/03 07:26:41 kardel Exp $ */
2 2
3/* 3/*
4 * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A 4 * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
5 * 5 *
6 * refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A 6 * refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
7 * 7 *
8 * generic reference clock driver for several DCF/GPS/MSF/... receivers 8 * generic reference clock driver for several DCF/GPS/MSF/... receivers
9 * 9 *
10 * PPS notes: 10 * PPS notes:
11 * On systems that support PPSAPI (RFC2783) PPSAPI is the 11 * On systems that support PPSAPI (RFC2783) PPSAPI is the
12 * preferred interface. 12 * preferred interface.
13 * 13 *
14 * Optionally make use of a STREAMS module for input processing where 14 * Optionally make use of a STREAMS module for input processing where
15 * available and configured. This STREAMS module reduces the time 15 * available and configured. This STREAMS module reduces the time
16 * stamp latency for serial and PPS events. 16 * stamp latency for serial and PPS events.
17 * Currently the STREAMS module is only available for Suns running 17 * Currently the STREAMS module is only available for Suns running
18 * SunOS 4.x and SunOS5.x. 18 * SunOS 4.x and SunOS5.x.
19 * 19 *
20 * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org> 20 * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
21 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 21 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
22 * 22 *
23 * Redistribution and use in source and binary forms, with or without 23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions 24 * modification, are permitted provided that the following conditions
25 * are met: 25 * are met:
26 * 1. Redistributions of source code must retain the above copyright 26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer. 27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright 28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the 29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution. 30 * documentation and/or other materials provided with the distribution.
31 * 3. Neither the name of the author nor the names of its contributors 31 * 3. Neither the name of the author nor the names of its contributors
32 * may be used to endorse or promote products derived from this software 32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission. 33 * without specific prior written permission.
34 * 34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE. 45 * SUCH DAMAGE.
46 * 46 *
47 */ 47 */
48 48
49#ifdef HAVE_CONFIG_H 49#ifdef HAVE_CONFIG_H
50# include "config.h" 50# include "config.h"
51#endif 51#endif
52 52
53#include "ntp_types.h" 53#include "ntp_types.h"
54 54
55#if defined(REFCLOCK) && defined(CLOCK_PARSE) 55#if defined(REFCLOCK) && defined(CLOCK_PARSE)
56 56
57/* 57/*
58 * This driver currently provides the support for 58 * This driver currently provides the support for
59 * - Meinberg receiver DCF77 PZF535 (TCXO version) (DCF) 59 * - Meinberg receiver DCF77 PZF535 (TCXO version) (DCF)
60 * - Meinberg receiver DCF77 PZF535 (OCXO version) (DCF) 60 * - Meinberg receiver DCF77 PZF535 (OCXO version) (DCF)
61 * - Meinberg receiver DCF77 PZF509 (DCF) 61 * - Meinberg receiver DCF77 PZF509 (DCF)
62 * - Meinberg receiver DCF77 AM receivers (e.g. C51) (DCF) 62 * - Meinberg receiver DCF77 AM receivers (e.g. C51) (DCF)
63 * - IGEL CLOCK (DCF) 63 * - IGEL CLOCK (DCF)
64 * - ELV DCF7000 (DCF) 64 * - ELV DCF7000 (DCF)
65 * - Schmid clock (DCF) 65 * - Schmid clock (DCF)
66 * - Conrad DCF77 receiver module (DCF) 66 * - Conrad DCF77 receiver module (DCF)
67 * - FAU DCF77 NTP receiver (TimeBrick) (DCF) 67 * - FAU DCF77 NTP receiver (TimeBrick) (DCF)
68 * - WHARTON 400A Series clock (DCF) 68 * - WHARTON 400A Series clock (DCF)
69 * 69 *
70 * - Meinberg GPS receivers (GPS) 70 * - Meinberg GPS receivers (GPS)
71 * - Trimble (TSIP and TAIP protocol) (GPS) 71 * - Trimble (TSIP and TAIP protocol) (GPS)
72 * 72 *
73 * - RCC8000 MSF Receiver (MSF) 73 * - RCC8000 MSF Receiver (MSF)
74 * - VARITEXT clock (MSF) 74 * - VARITEXT clock (MSF)
75 */ 75 */
76 76
77/* 77/*
78 * Meinberg receivers are usually connected via a 78 * Meinberg receivers are usually connected via a
79 * 9600/7E1 or 19200/8N1 serial line. 79 * 9600/7E1 or 19200/8N1 serial line.
80 * 80 *
81 * The Meinberg GPS receivers also have a special NTP time stamp 81 * The Meinberg GPS receivers also have a special NTP time stamp
82 * format. The firmware release is Uni-Erlangen. 82 * format. The firmware release is Uni-Erlangen.
83 * 83 *
84 * Meinberg generic receiver setup: 84 * Meinberg generic receiver setup:
85 * output time code every second 85 * output time code every second
86 * Baud rate 9600 7E2S 86 * Baud rate 9600 7E2S
87 * 87 *
88 * Meinberg GPS receiver setup: 88 * Meinberg GPS receiver setup:
89 * output time code every second 89 * output time code every second
90 * Baudrate 19200 8N1 90 * Baudrate 19200 8N1
91 * 91 *
92 * This software supports the standard data formats used 92 * This software supports the standard data formats used
93 * in Meinberg receivers. 93 * in Meinberg receivers.
94 * 94 *
95 * Special software versions are only sensible for the 95 * Special software versions are only sensible for the
96 * oldest GPS receiver, GPS16x. For newer receiver types 96 * oldest GPS receiver, GPS16x. For newer receiver types
97 * the output string format can be configured at the device, 97 * the output string format can be configured at the device,
98 * and the device name is generally GPSxxx instead of GPS16x. 98 * and the device name is generally GPSxxx instead of GPS16x.
99 * 99 *
100 * Meinberg can be reached via: http://www.meinberg.de/ 100 * Meinberg can be reached via: http://www.meinberg.de/
101 */ 101 */
102 102
103#include "ntpd.h" 103#include "ntpd.h"
104#include "ntp_refclock.h" 104#include "ntp_refclock.h"
105#include "timevalops.h" /* includes <sys/time.h> */ 105#include "timevalops.h" /* includes <sys/time.h> */
106#include "ntp_control.h" 106#include "ntp_control.h"
107#include "ntp_string.h" 107#include "ntp_string.h"
108 108
109#include <stdio.h> 109#include <stdio.h>
110#include <ctype.h> 110#include <ctype.h>
111#ifndef TM_IN_SYS_TIME 111#ifndef TM_IN_SYS_TIME
112# include <time.h> 112# include <time.h>
113#endif 113#endif
114 114
115#ifdef HAVE_UNISTD_H 115#ifdef HAVE_UNISTD_H
116# include <unistd.h> 116# include <unistd.h>
117#endif 117#endif
118 118
119#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS) 119#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
120# include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}" 120# include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"
121#endif 121#endif
122 122
123#ifdef STREAM 123#ifdef STREAM
124# include <sys/stream.h> 124# include <sys/stream.h>
125# include <sys/stropts.h> 125# include <sys/stropts.h>
126#endif 126#endif
127 127
128#ifdef HAVE_TERMIOS 128#ifdef HAVE_TERMIOS
129# include <termios.h> 129# include <termios.h>
130# define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_)) 130# define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
131# define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_)) 131# define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
132# undef HAVE_SYSV_TTYS 132# undef HAVE_SYSV_TTYS
133#endif 133#endif
134 134
135#ifdef HAVE_SYSV_TTYS 135#ifdef HAVE_SYSV_TTYS
136# define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_)) 136# define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
137# define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_)) 137# define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
138#endif 138#endif
139 139
140#ifdef HAVE_BSD_TTYS 140#ifdef HAVE_BSD_TTYS
141/* #error CURRENTLY NO BSD TTY SUPPORT */ 141/* #error CURRENTLY NO BSD TTY SUPPORT */
142# include "Bletch: BSD TTY not currently supported" 142# include "Bletch: BSD TTY not currently supported"
143#endif 143#endif
144 144
145#ifdef HAVE_SYS_IOCTL_H 145#ifdef HAVE_SYS_IOCTL_H
146# include <sys/ioctl.h> 146# include <sys/ioctl.h>
147#endif 147#endif
148 148
149#ifdef HAVE_PPSAPI 149#ifdef HAVE_PPSAPI
150# include "ppsapi_timepps.h" 150# include "ppsapi_timepps.h"
151# include "refclock_atom.h" 151# include "refclock_atom.h"
152#endif 152#endif
153 153
154#ifdef PPS 154#ifdef PPS
155# ifdef HAVE_SYS_PPSCLOCK_H 155# ifdef HAVE_SYS_PPSCLOCK_H
156# include <sys/ppsclock.h> 156# include <sys/ppsclock.h>
157# endif 157# endif
158# ifdef HAVE_TIO_SERIAL_STUFF 158# ifdef HAVE_TIO_SERIAL_STUFF
159# include <linux/serial.h> 159# include <linux/serial.h>
160# endif 160# endif
161#endif 161#endif
162 162
163# define BUFFER_SIZE(_BUF, _PTR) ((int)((_BUF) + sizeof(_BUF) - (_PTR))) 163# define BUFFER_SIZE(_BUF, _PTR) ((int)((_BUF) + sizeof(_BUF) - (_PTR)))
164# define BUFFER_SIZES(_BUF, _PTR, _SZ) ((int)((_BUF) + (_SZ) - (_PTR))) 164# define BUFFER_SIZES(_BUF, _PTR, _SZ) ((int)((_BUF) + (_SZ) - (_PTR)))
165 165
166/* 166/*
167 * document type of PPS interfacing - copy of ifdef mechanism in local_input() 167 * document type of PPS interfacing - copy of ifdef mechanism in local_input()
168 */ 168 */
169#undef PPS_METHOD 169#undef PPS_METHOD
170 170
171#ifdef HAVE_PPSAPI 171#ifdef HAVE_PPSAPI
172#define PPS_METHOD "PPS API" 172#define PPS_METHOD "PPS API"
173#else 173#else
174#ifdef TIOCDCDTIMESTAMP 174#ifdef TIOCDCDTIMESTAMP
175#define PPS_METHOD "TIOCDCDTIMESTAMP" 175#define PPS_METHOD "TIOCDCDTIMESTAMP"
176#else /* TIOCDCDTIMESTAMP */ 176#else /* TIOCDCDTIMESTAMP */
177#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV)) 177#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
178#ifdef HAVE_CIOGETEV 178#ifdef HAVE_CIOGETEV
179#define PPS_METHOD "CIOGETEV" 179#define PPS_METHOD "CIOGETEV"
180#endif 180#endif
181#ifdef HAVE_TIOCGPPSEV 181#ifdef HAVE_TIOCGPPSEV
182#define PPS_METHOD "TIOCGPPSEV" 182#define PPS_METHOD "TIOCGPPSEV"
183#endif 183#endif
184#endif 184#endif
185#endif /* TIOCDCDTIMESTAMP */ 185#endif /* TIOCDCDTIMESTAMP */
186#endif /* HAVE_PPSAPI */ 186#endif /* HAVE_PPSAPI */
187 187
188/* 188/*
189 * COND_DEF can be conditionally defined as DEF or 0. If defined as DEF 189 * COND_DEF can be conditionally defined as DEF or 0. If defined as DEF
190 * then some more parse-specific variables are flagged to be printed with 190 * then some more parse-specific variables are flagged to be printed with
191 * "ntpq -c cv <assid>". This can be lengthy, so by default COND_DEF 191 * "ntpq -c cv <assid>". This can be lengthy, so by default COND_DEF
192 * should be defined as 0. 192 * should be defined as 0.
193 */ 193 */
194#if 0 194#if 0
195# define COND_DEF DEF // enable this for testing 195# define COND_DEF DEF // enable this for testing
196#else 196#else
197# define COND_DEF 0 // enable this by default 197# define COND_DEF 0 // enable this by default
198#endif 198#endif
199 199
200#include "ntp_io.h" 200#include "ntp_io.h"
201#include "ntp_stdlib.h" 201#include "ntp_stdlib.h"
202 202
203#include "parse.h" 203#include "parse.h"
204#include "mbg_gps166.h" 204#include "mbg_gps166.h"
205#include "trimble.h" 205#include "trimble.h"
206#include "binio.h" 206#include "binio.h"
207#include "ascii.h" 207#include "ascii.h"
208#include "ieee754io.h" 208#include "ieee754io.h"
209#include "recvbuff.h" 209#include "recvbuff.h"
210 210
211static char rcsid[] = "refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A+POWERUPTRUST"; 211static char rcsid[] = "refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A+POWERUPTRUST";
212 212
213/**=========================================================================== 213/**===========================================================================
214 ** external interface to ntp mechanism 214 ** external interface to ntp mechanism
215 **/ 215 **/
216 216
217static int parse_start (int, struct peer *); 217static int parse_start (int, struct peer *);
218static void parse_shutdown (int, struct peer *); 218static void parse_shutdown (int, struct peer *);
219static void parse_poll (int, struct peer *); 219static void parse_poll (int, struct peer *);
220static void parse_control (int, const struct refclockstat *, struct refclockstat *, struct peer *); 220static void parse_control (int, const struct refclockstat *, struct refclockstat *, struct peer *);
221 221
222struct refclock refclock_parse = { 222struct refclock refclock_parse = {
223 parse_start, 223 parse_start,
224 parse_shutdown, 224 parse_shutdown,
225 parse_poll, 225 parse_poll,
226 parse_control, 226 parse_control,
227 noentry, 227 noentry,
228 noentry, 228 noentry,
229 NOFLAGS 229 NOFLAGS
230}; 230};
231 231
232/* 232/*
233 * Definitions 233 * Definitions
234 */ 234 */
235#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */ 235#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
236#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */ 236#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
237#define PARSEPPSDEVICE "/dev/refclockpps-%d" /* optional pps device to open %d is unit number */ 237#define PARSEPPSDEVICE "/dev/refclockpps-%d" /* optional pps device to open %d is unit number */
238 238
239#undef ABS 239#undef ABS
240#define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_)) 240#define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
241 241
242#define PARSE_HARDPPS_DISABLE 0 242#define PARSE_HARDPPS_DISABLE 0
243#define PARSE_HARDPPS_ENABLE 1 243#define PARSE_HARDPPS_ENABLE 1
244 244
245/**=========================================================================== 245/**===========================================================================
246 ** function vector for dynamically binding io handling mechanism 246 ** function vector for dynamically binding io handling mechanism
247 **/ 247 **/
248 248
249struct parseunit; /* to keep inquiring minds happy */ 249struct parseunit; /* to keep inquiring minds happy */
250 250
251typedef struct bind 251typedef struct bind
252{ 252{
253 const char *bd_description; /* name of type of binding */ 253 const char *bd_description; /* name of type of binding */
254 int (*bd_init) (struct parseunit *); /* initialize */ 254 int (*bd_init) (struct parseunit *); /* initialize */
255 void (*bd_end) (struct parseunit *); /* end */ 255 void (*bd_end) (struct parseunit *); /* end */
256 int (*bd_setcs) (struct parseunit *, parsectl_t *); /* set character size */ 256 int (*bd_setcs) (struct parseunit *, parsectl_t *); /* set character size */
257 int (*bd_disable) (struct parseunit *); /* disable */ 257 int (*bd_disable) (struct parseunit *); /* disable */
258 int (*bd_enable) (struct parseunit *); /* enable */ 258 int (*bd_enable) (struct parseunit *); /* enable */
259 int (*bd_getfmt) (struct parseunit *, parsectl_t *); /* get format */ 259 int (*bd_getfmt) (struct parseunit *, parsectl_t *); /* get format */
260 int (*bd_setfmt) (struct parseunit *, parsectl_t *); /* setfmt */ 260 int (*bd_setfmt) (struct parseunit *, parsectl_t *); /* setfmt */
261 int (*bd_timecode) (struct parseunit *, parsectl_t *); /* get time code */ 261 int (*bd_timecode) (struct parseunit *, parsectl_t *); /* get time code */
262 void (*bd_receive) (struct recvbuf *); /* receive operation */ 262 void (*bd_receive) (struct recvbuf *); /* receive operation */
263 int (*bd_io_input) (struct recvbuf *); /* input operation */ 263 int (*bd_io_input) (struct recvbuf *); /* input operation */
264} bind_t; 264} bind_t;
265 265
266#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_) 266#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
267#define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_) 267#define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)
268#define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_) 268#define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)
269#define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_) 269#define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)
270#define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_) 270#define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
271#define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_) 271#define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
272#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_) 272#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
273 273
274/* 274/*
275 * special handling flags 275 * special handling flags
276 */ 276 */
277#define PARSE_F_PPSONSECOND 0x00000001 /* PPS pulses are on second */ 277#define PARSE_F_PPSONSECOND 0x00000001 /* PPS pulses are on second */
278#define PARSE_F_POWERUPTRUST 0x00000100 /* POWERUP state ist trusted for */ 278#define PARSE_F_POWERUPTRUST 0x00000100 /* POWERUP state ist trusted for */
279 /* trusttime after SYNC was seen */ 279 /* trusttime after SYNC was seen */
280/**=========================================================================== 280/**===========================================================================
281 ** error message regression handling 281 ** error message regression handling
282 ** 282 **
283 ** there are quite a few errors that can occur in rapid succession such as 283 ** there are quite a few errors that can occur in rapid succession such as
284 ** noisy input data or no data at all. in order to reduce the amount of 284 ** noisy input data or no data at all. in order to reduce the amount of
285 ** syslog messages in such case, we are using a backoff algorithm. We limit 285 ** syslog messages in such case, we are using a backoff algorithm. We limit
286 ** the number of error messages of a certain class to 1 per time unit. if a 286 ** the number of error messages of a certain class to 1 per time unit. if a
287 ** configurable number of messages is displayed that way, we move on to the 287 ** configurable number of messages is displayed that way, we move on to the
288 ** next time unit / count for that class. a count of messages that have been 288 ** next time unit / count for that class. a count of messages that have been
289 ** suppressed is held and displayed whenever a corresponding message is 289 ** suppressed is held and displayed whenever a corresponding message is
290 ** displayed. the time units for a message class will also be displayed. 290 ** displayed. the time units for a message class will also be displayed.
291 ** whenever an error condition clears we reset the error message state, 291 ** whenever an error condition clears we reset the error message state,
292 ** thus we would still generate much output on pathological conditions 292 ** thus we would still generate much output on pathological conditions
293 ** where the system oscillates between OK and NOT OK states. coping 293 ** where the system oscillates between OK and NOT OK states. coping
294 ** with that condition is currently considered too complicated. 294 ** with that condition is currently considered too complicated.
295 **/ 295 **/
296 296
297#define ERR_ALL (unsigned)~0 /* "all" errors */ 297#define ERR_ALL (unsigned)~0 /* "all" errors */
298#define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */ 298#define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */
299#define ERR_NODATA (unsigned)1 /* no input data */ 299#define ERR_NODATA (unsigned)1 /* no input data */
300#define ERR_BADIO (unsigned)2 /* read/write/select errors */ 300#define ERR_BADIO (unsigned)2 /* read/write/select errors */
301#define ERR_BADSTATUS (unsigned)3 /* unsync states */ 301#define ERR_BADSTATUS (unsigned)3 /* unsync states */
302#define ERR_BADEVENT (unsigned)4 /* non nominal events */ 302#define ERR_BADEVENT (unsigned)4 /* non nominal events */
303#define ERR_INTERNAL (unsigned)5 /* internal error */ 303#define ERR_INTERNAL (unsigned)5 /* internal error */
304#define ERR_CNT (unsigned)(ERR_INTERNAL+1) 304#define ERR_CNT (unsigned)(ERR_INTERNAL+1)
305 305
306#define ERR(_X_) if (list_err(parse, (_X_))) 306#define ERR(_X_) if (list_err(parse, (_X_)))
307 307
308struct errorregression 308struct errorregression
309{ 309{
310 u_long err_count; /* number of repititions per class */ 310 u_long err_count; /* number of repititions per class */
311 u_long err_delay; /* minimum delay between messages */ 311 u_long err_delay; /* minimum delay between messages */
312}; 312};
313 313
314static struct errorregression 314static struct errorregression
315err_baddata[] = /* error messages for bad input data */ 315err_baddata[] = /* error messages for bad input data */
316{ 316{
317 { 1, 0 }, /* output first message immediately */ 317 { 1, 0 }, /* output first message immediately */
318 { 5, 60 }, /* output next five messages in 60 second intervals */ 318 { 5, 60 }, /* output next five messages in 60 second intervals */
319 { 3, 3600 }, /* output next 3 messages in hour intervals */ 319 { 3, 3600 }, /* output next 3 messages in hour intervals */
320 { 0, 12*3600 } /* repeat messages only every 12 hours */ 320 { 0, 12*3600 } /* repeat messages only every 12 hours */
321}; 321};
322 322
323static struct errorregression 323static struct errorregression
324err_nodata[] = /* error messages for missing input data */ 324err_nodata[] = /* error messages for missing input data */
325{ 325{
326 { 1, 0 }, /* output first message immediately */ 326 { 1, 0 }, /* output first message immediately */
327 { 5, 60 }, /* output next five messages in 60 second intervals */ 327 { 5, 60 }, /* output next five messages in 60 second intervals */
328 { 3, 3600 }, /* output next 3 messages in hour intervals */ 328 { 3, 3600 }, /* output next 3 messages in hour intervals */
329 { 0, 12*3600 } /* repeat messages only every 12 hours */ 329 { 0, 12*3600 } /* repeat messages only every 12 hours */
330}; 330};
331 331
332static struct errorregression 332static struct errorregression
333err_badstatus[] = /* unsynchronized state messages */ 333err_badstatus[] = /* unsynchronized state messages */
334{ 334{
335 { 1, 0 }, /* output first message immediately */ 335 { 1, 0 }, /* output first message immediately */
336 { 5, 60 }, /* output next five messages in 60 second intervals */ 336 { 5, 60 }, /* output next five messages in 60 second intervals */
337 { 3, 3600 }, /* output next 3 messages in hour intervals */ 337 { 3, 3600 }, /* output next 3 messages in hour intervals */
338 { 0, 12*3600 } /* repeat messages only every 12 hours */ 338 { 0, 12*3600 } /* repeat messages only every 12 hours */
339}; 339};
340 340
341static struct errorregression 341static struct errorregression
342err_badio[] = /* io failures (bad reads, selects, ...) */ 342err_badio[] = /* io failures (bad reads, selects, ...) */
343{ 343{
344 { 1, 0 }, /* output first message immediately */ 344 { 1, 0 }, /* output first message immediately */
345 { 5, 60 }, /* output next five messages in 60 second intervals */ 345 { 5, 60 }, /* output next five messages in 60 second intervals */
346 { 5, 3600 }, /* output next 3 messages in hour intervals */ 346 { 5, 3600 }, /* output next 3 messages in hour intervals */
347 { 0, 12*3600 } /* repeat messages only every 12 hours */ 347 { 0, 12*3600 } /* repeat messages only every 12 hours */
348}; 348};
349 349
350static struct errorregression 350static struct errorregression
351err_badevent[] = /* non nominal events */ 351err_badevent[] = /* non nominal events */
352{ 352{
353 { 20, 0 }, /* output first message immediately */ 353 { 20, 0 }, /* output first message immediately */
354 { 6, 60 }, /* output next five messages in 60 second intervals */ 354 { 6, 60 }, /* output next five messages in 60 second intervals */
355 { 5, 3600 }, /* output next 3 messages in hour intervals */ 355 { 5, 3600 }, /* output next 3 messages in hour intervals */
356 { 0, 12*3600 } /* repeat messages only every 12 hours */ 356 { 0, 12*3600 } /* repeat messages only every 12 hours */
357}; 357};
358 358
359static struct errorregression 359static struct errorregression
360err_internal[] = /* really bad things - basically coding/OS errors */ 360err_internal[] = /* really bad things - basically coding/OS errors */
361{ 361{
362 { 0, 0 }, /* output all messages immediately */ 362 { 0, 0 }, /* output all messages immediately */
363}; 363};
364 364
365static struct errorregression * 365static struct errorregression *
366err_tbl[] = 366err_tbl[] =
367{ 367{
368 err_baddata, 368 err_baddata,
369 err_nodata, 369 err_nodata,
370 err_badio, 370 err_badio,
371 err_badstatus, 371 err_badstatus,
372 err_badevent, 372 err_badevent,
373 err_internal 373 err_internal
374}; 374};
375 375
376struct errorinfo 376struct errorinfo
377{ 377{
378 u_long err_started; /* begin time (ntp) of error condition */ 378 u_long err_started; /* begin time (ntp) of error condition */
379 u_long err_last; /* last time (ntp) error occurred */ 379 u_long err_last; /* last time (ntp) error occurred */
380 u_long err_cnt; /* number of error repititions */ 380 u_long err_cnt; /* number of error repititions */
381 u_long err_suppressed; /* number of suppressed messages */ 381 u_long err_suppressed; /* number of suppressed messages */
382 struct errorregression *err_stage; /* current error stage */ 382 struct errorregression *err_stage; /* current error stage */
383}; 383};
384 384
385/**=========================================================================== 385/**===========================================================================
386 ** refclock instance data 386 ** refclock instance data
387 **/ 387 **/
388 388
389struct parseunit 389struct parseunit
390{ 390{
391 /* 391 /*
392 * NTP management 392 * NTP management
393 */ 393 */
394 struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */ 394 struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
395 struct refclockproc *generic; /* backlink to refclockproc structure */ 395 struct refclockproc *generic; /* backlink to refclockproc structure */
396 396
397 /* 397 /*
398 * PARSE io 398 * PARSE io
399 */ 399 */
400 bind_t *binding; /* io handling binding */ 400 bind_t *binding; /* io handling binding */
401 401
402 /* 402 /*
403 * parse state 403 * parse state
404 */ 404 */
405 parse_t parseio; /* io handling structure (user level parsing) */ 405 parse_t parseio; /* io handling structure (user level parsing) */
406 406
407 /* 407 /*
408 * type specific parameters 408 * type specific parameters
409 */ 409 */
410 struct parse_clockinfo *parse_type; /* link to clock description */ 410 struct parse_clockinfo *parse_type; /* link to clock description */
411 411
412 /* 412 /*
413 * clock state handling/reporting 413 * clock state handling/reporting
414 */ 414 */
415 u_char flags; /* flags (leap_control) */ 415 u_char flags; /* flags (leap_control) */
416 u_long lastchange; /* time (ntp) when last state change accured */ 416 u_long lastchange; /* time (ntp) when last state change accured */
417 u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */ 417 u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
418 u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */ 418 u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */
419 u_short lastformat; /* last format used */ 419 u_short lastformat; /* last format used */
420 u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */ 420 u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */
421 u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */ 421 u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */
422 double ppsphaseadjust; /* phase adjustment of PPS time stamp */ 422 double ppsphaseadjust; /* phase adjustment of PPS time stamp */
423 u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */ 423 u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */
424 u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */ 424 u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
425 int ppsfd; /* fd to ise for PPS io */ 425 int ppsfd; /* fd to ise for PPS io */
426#ifdef HAVE_PPSAPI 426#ifdef HAVE_PPSAPI
427 int hardppsstate; /* current hard pps state */ 427 int hardppsstate; /* current hard pps state */
428 struct refclock_atom atom; /* PPSAPI structure */ 428 struct refclock_atom atom; /* PPSAPI structure */
429#endif 429#endif
430 parsetime_t timedata; /* last (parse module) data */ 430 parsetime_t timedata; /* last (parse module) data */
431 void *localdata; /* optional local, receiver-specific data */ 431 void *localdata; /* optional local, receiver-specific data */
432 unsigned long localstate; /* private local state */ 432 unsigned long localstate; /* private local state */
433 struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */ 433 struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */
434 struct ctl_var *kv; /* additional pseudo variables */ 434 struct ctl_var *kv; /* additional pseudo variables */
435 u_long laststatistic; /* time when staticstics where output */ 435 u_long laststatistic; /* time when staticstics where output */
436}; 436};
437 437
438 438
439/**=========================================================================== 439/**===========================================================================
440 ** Clockinfo section all parameter for specific clock types 440 ** Clockinfo section all parameter for specific clock types
441 ** includes NTP parameters, TTY parameters and IO handling parameters 441 ** includes NTP parameters, TTY parameters and IO handling parameters
442 **/ 442 **/
443 443
444static void poll_dpoll (struct parseunit *); 444static void poll_dpoll (struct parseunit *);
445static void poll_poll (struct peer *); 445static void poll_poll (struct peer *);
446static int poll_init (struct parseunit *); 446static int poll_init (struct parseunit *);
447 447
448typedef struct poll_info 448typedef struct poll_info
449{ 449{
450 u_long rate; /* poll rate - once every "rate" seconds - 0 off */ 450 u_long rate; /* poll rate - once every "rate" seconds - 0 off */
451 const char *string; /* string to send for polling */ 451 const char *string; /* string to send for polling */
452 u_long count; /* number of characters in string */ 452 u_long count; /* number of characters in string */
453} poll_info_t; 453} poll_info_t;
454 454
455#define NO_CL_FLAGS 0 455#define NO_CL_FLAGS 0
456#define NO_POLL 0 456#define NO_POLL 0
457#define NO_INIT 0 457#define NO_INIT 0
458#define NO_END 0 458#define NO_END 0
459#define NO_EVENT 0 459#define NO_EVENT 0
460#define NO_LCLDATA 0 460#define NO_LCLDATA 0
461#define NO_MESSAGE 0 461#define NO_MESSAGE 0
462#define NO_PPSDELAY 0 462#define NO_PPSDELAY 0
463 463
464#define DCF_ID "DCF" /* generic DCF */ 464#define DCF_ID "DCF" /* generic DCF */
465#define DCF_A_ID "DCFa" /* AM demodulation */ 465#define DCF_A_ID "DCFa" /* AM demodulation */
466#define DCF_P_ID "DCFp" /* psuedo random phase shift */ 466#define DCF_P_ID "DCFp" /* psuedo random phase shift */
467#define GPS_ID "GPS" /* GPS receiver */ 467#define GPS_ID "GPS" /* GPS receiver */
468 468
469#define NOCLOCK_ROOTDELAY 0.0 469#define NOCLOCK_ROOTDELAY 0.0
470#define NOCLOCK_BASEDELAY 0.0 470#define NOCLOCK_BASEDELAY 0.0
471#define NOCLOCK_DESCRIPTION 0 471#define NOCLOCK_DESCRIPTION 0
472#define NOCLOCK_MAXUNSYNC 0 472#define NOCLOCK_MAXUNSYNC 0
473#define NOCLOCK_CFLAG 0 473#define NOCLOCK_CFLAG 0
474#define NOCLOCK_IFLAG 0 474#define NOCLOCK_IFLAG 0
475#define NOCLOCK_OFLAG 0 475#define NOCLOCK_OFLAG 0
476#define NOCLOCK_LFLAG 0 476#define NOCLOCK_LFLAG 0
477#define NOCLOCK_ID "TILT" 477#define NOCLOCK_ID "TILT"
478#define NOCLOCK_POLL NO_POLL 478#define NOCLOCK_POLL NO_POLL
479#define NOCLOCK_INIT NO_INIT 479#define NOCLOCK_INIT NO_INIT
480#define NOCLOCK_END NO_END 480#define NOCLOCK_END NO_END
481#define NOCLOCK_DATA NO_LCLDATA 481#define NOCLOCK_DATA NO_LCLDATA
482#define NOCLOCK_FORMAT "" 482#define NOCLOCK_FORMAT ""
483#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC 483#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
484#define NOCLOCK_SAMPLES 0 484#define NOCLOCK_SAMPLES 0
485#define NOCLOCK_KEEP 0 485#define NOCLOCK_KEEP 0
486 486
487#define DCF_TYPE CTL_SST_TS_LF 487#define DCF_TYPE CTL_SST_TS_LF
488#define GPS_TYPE CTL_SST_TS_UHF 488#define GPS_TYPE CTL_SST_TS_UHF
489 489
490/* 490/*
491 * receiver specific constants 491 * receiver specific constants
492 */ 492 */
493#define MBG_SPEED (B9600) 493#define MBG_SPEED (B9600)
494#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB) 494#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)
495#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP) 495#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
496#define MBG_OFLAG 0 496#define MBG_OFLAG 0
497#define MBG_LFLAG 0 497#define MBG_LFLAG 0
498#define MBG_FLAGS PARSE_F_PPSONSECOND 498#define MBG_FLAGS PARSE_F_PPSONSECOND
499 499
500/* 500/*
501 * Meinberg DCF77 receivers 501 * Meinberg DCF77 receivers
502 */ 502 */
503#define DCFUA31_ROOTDELAY 0.0 /* 0 */ 503#define DCFUA31_ROOTDELAY 0.0 /* 0 */
504#define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */ 504#define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */
505#define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible" 505#define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible"
506#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */ 506#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
507#define DCFUA31_SPEED MBG_SPEED 507#define DCFUA31_SPEED MBG_SPEED
508#define DCFUA31_CFLAG MBG_CFLAG 508#define DCFUA31_CFLAG MBG_CFLAG
509#define DCFUA31_IFLAG MBG_IFLAG 509#define DCFUA31_IFLAG MBG_IFLAG
510#define DCFUA31_OFLAG MBG_OFLAG 510#define DCFUA31_OFLAG MBG_OFLAG
511#define DCFUA31_LFLAG MBG_LFLAG 511#define DCFUA31_LFLAG MBG_LFLAG
512#define DCFUA31_SAMPLES 5 512#define DCFUA31_SAMPLES 5
513#define DCFUA31_KEEP 3 513#define DCFUA31_KEEP 3
514#define DCFUA31_FORMAT "Meinberg Standard" 514#define DCFUA31_FORMAT "Meinberg Standard"
515 515
516/* 516/*
517 * Meinberg DCF PZF535/TCXO (FM/PZF) receiver 517 * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
518 */ 518 */
519#define DCFPZF535_ROOTDELAY 0.0 519#define DCFPZF535_ROOTDELAY 0.0
520#define DCFPZF535_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */ 520#define DCFPZF535_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
521#define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/509 / TCXO" 521#define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/509 / TCXO"
522#define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours 522#define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours
523 * @ 5e-8df/f we have accumulated 523 * @ 5e-8df/f we have accumulated
524 * at most 2.16 ms (thus we move to 524 * at most 2.16 ms (thus we move to
525 * NTP synchronisation */ 525 * NTP synchronisation */
526#define DCFPZF535_SPEED MBG_SPEED 526#define DCFPZF535_SPEED MBG_SPEED
527#define DCFPZF535_CFLAG MBG_CFLAG 527#define DCFPZF535_CFLAG MBG_CFLAG
528#define DCFPZF535_IFLAG MBG_IFLAG 528#define DCFPZF535_IFLAG MBG_IFLAG
529#define DCFPZF535_OFLAG MBG_OFLAG 529#define DCFPZF535_OFLAG MBG_OFLAG
530#define DCFPZF535_LFLAG MBG_LFLAG 530#define DCFPZF535_LFLAG MBG_LFLAG
531#define DCFPZF535_SAMPLES 5 531#define DCFPZF535_SAMPLES 5
532#define DCFPZF535_KEEP 3 532#define DCFPZF535_KEEP 3
533#define DCFPZF535_FORMAT "Meinberg Standard" 533#define DCFPZF535_FORMAT "Meinberg Standard"
534 534
535/* 535/*
536 * Meinberg DCF PZF535/OCXO receiver 536 * Meinberg DCF PZF535/OCXO receiver
537 */ 537 */
538#define DCFPZF535OCXO_ROOTDELAY 0.0 538#define DCFPZF535OCXO_ROOTDELAY 0.0
539#define DCFPZF535OCXO_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */ 539#define DCFPZF535OCXO_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
540#define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / OCXO" 540#define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / OCXO"
541#define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days 541#define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
542 * @ 5e-9df/f we have accumulated 542 * @ 5e-9df/f we have accumulated
543 * at most an error of 1.73 ms 543 * at most an error of 1.73 ms
544 * (thus we move to NTP synchronisation) */ 544 * (thus we move to NTP synchronisation) */
545#define DCFPZF535OCXO_SPEED MBG_SPEED 545#define DCFPZF535OCXO_SPEED MBG_SPEED
546#define DCFPZF535OCXO_CFLAG MBG_CFLAG 546#define DCFPZF535OCXO_CFLAG MBG_CFLAG
547#define DCFPZF535OCXO_IFLAG MBG_IFLAG 547#define DCFPZF535OCXO_IFLAG MBG_IFLAG
548#define DCFPZF535OCXO_OFLAG MBG_OFLAG 548#define DCFPZF535OCXO_OFLAG MBG_OFLAG
549#define DCFPZF535OCXO_LFLAG MBG_LFLAG 549#define DCFPZF535OCXO_LFLAG MBG_LFLAG
550#define DCFPZF535OCXO_SAMPLES 5 550#define DCFPZF535OCXO_SAMPLES 5
551#define DCFPZF535OCXO_KEEP 3 551#define DCFPZF535OCXO_KEEP 3
552#define DCFPZF535OCXO_FORMAT "Meinberg Standard" 552#define DCFPZF535OCXO_FORMAT "Meinberg Standard"
553 553
554/* 554/*
555 * Meinberg GPS receivers 555 * Meinberg GPS receivers
556 */ 556 */
557static void gps16x_message (struct parseunit *, parsetime_t *); 557static void gps16x_message (struct parseunit *, parsetime_t *);
558static int gps16x_poll_init (struct parseunit *); 558static int gps16x_poll_init (struct parseunit *);
559 559
560#define GPS16X_ROOTDELAY 0.0 /* nothing here */ 560#define GPS16X_ROOTDELAY 0.0 /* nothing here */
561#define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */ 561#define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
562#define GPS16X_DESCRIPTION "Meinberg GPS receiver" 562#define GPS16X_DESCRIPTION "Meinberg GPS receiver"
563#define GPS16X_MAXUNSYNC 60*60*96 /* only trust clock for 4 days 563#define GPS16X_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
564 * @ 5e-9df/f we have accumulated 564 * @ 5e-9df/f we have accumulated
565 * at most an error of 1.73 ms 565 * at most an error of 1.73 ms
566 * (thus we move to NTP synchronisation) */ 566 * (thus we move to NTP synchronisation) */
567#define GPS16X_SPEED B19200 567#define GPS16X_SPEED B19200
568#define GPS16X_CFLAG (CS8|CREAD|CLOCAL|HUPCL) 568#define GPS16X_CFLAG (CS8|CREAD|CLOCAL|HUPCL)
569#define GPS16X_IFLAG (IGNBRK|IGNPAR) 569#define GPS16X_IFLAG (IGNBRK|IGNPAR)
570#define GPS16X_OFLAG MBG_OFLAG 570#define GPS16X_OFLAG MBG_OFLAG
571#define GPS16X_LFLAG MBG_LFLAG 571#define GPS16X_LFLAG MBG_LFLAG
572#define GPS16X_POLLRATE 6 572#define GPS16X_POLLRATE 6
573#define GPS16X_POLLCMD "" 573#define GPS16X_POLLCMD ""
574#define GPS16X_CMDSIZE 0 574#define GPS16X_CMDSIZE 0
575 575
576static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE }; 576static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE };
577 577
578#define GPS16X_INIT gps16x_poll_init 578#define GPS16X_INIT gps16x_poll_init
579#define GPS16X_POLL 0 579#define GPS16X_POLL 0
580#define GPS16X_END 0 580#define GPS16X_END 0
581#define GPS16X_DATA ((void *)(&gps16x_pollinfo)) 581#define GPS16X_DATA ((void *)(&gps16x_pollinfo))
582#define GPS16X_MESSAGE gps16x_message 582#define GPS16X_MESSAGE gps16x_message
583#define GPS16X_ID GPS_ID 583#define GPS16X_ID GPS_ID
584#define GPS16X_FORMAT "Meinberg GPS Extended" 584#define GPS16X_FORMAT "Meinberg GPS Extended"
585#define GPS16X_SAMPLES 5 585#define GPS16X_SAMPLES 5
586#define GPS16X_KEEP 3 586#define GPS16X_KEEP 3
587 587
588/* 588/*
589 * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit) 589 * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
590 * 590 *
591 * This is really not the hottest clock - but before you have nothing ... 591 * This is really not the hottest clock - but before you have nothing ...
592 */ 592 */
593#define DCF7000_ROOTDELAY 0.0 /* 0 */ 593#define DCF7000_ROOTDELAY 0.0 /* 0 */
594#define DCF7000_BASEDELAY 0.405 /* slow blow */ 594#define DCF7000_BASEDELAY 0.405 /* slow blow */
595#define DCF7000_DESCRIPTION "ELV DCF7000" 595#define DCF7000_DESCRIPTION "ELV DCF7000"
596#define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */ 596#define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
597#define DCF7000_SPEED (B9600) 597#define DCF7000_SPEED (B9600)
598#define DCF7000_CFLAG (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL) 598#define DCF7000_CFLAG (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
599#define DCF7000_IFLAG (IGNBRK) 599#define DCF7000_IFLAG (IGNBRK)
600#define DCF7000_OFLAG 0 600#define DCF7000_OFLAG 0
601#define DCF7000_LFLAG 0 601#define DCF7000_LFLAG 0
602#define DCF7000_SAMPLES 5 602#define DCF7000_SAMPLES 5
603#define DCF7000_KEEP 3 603#define DCF7000_KEEP 3
604#define DCF7000_FORMAT "ELV DCF7000" 604#define DCF7000_FORMAT "ELV DCF7000"
605 605
606/* 606/*
607 * Schmid DCF Receiver Kit 607 * Schmid DCF Receiver Kit
608 * 608 *
609 * When the WSDCF clock is operating optimally we want the primary clock 609 * When the WSDCF clock is operating optimally we want the primary clock
610 * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer 610 * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer
611 * structure is set to 290 ms and we compute delays which are at least 611 * structure is set to 290 ms and we compute delays which are at least
612 * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format 612 * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format
613 */ 613 */
614#define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */ 614#define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */
615#define WS_POLLCMD "\163" 615#define WS_POLLCMD "\163"
616#define WS_CMDSIZE 1 616#define WS_CMDSIZE 1
617 617
618static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE }; 618static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
619 619
620#define WSDCF_INIT poll_init 620#define WSDCF_INIT poll_init
621#define WSDCF_POLL poll_dpoll 621#define WSDCF_POLL poll_dpoll
622#define WSDCF_END 0 622#define WSDCF_END 0
623#define WSDCF_DATA ((void *)(&wsdcf_pollinfo)) 623#define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
624#define WSDCF_ROOTDELAY 0.0 /* 0 */ 624#define WSDCF_ROOTDELAY 0.0 /* 0 */
625#define WSDCF_BASEDELAY 0.010 /* ~ 10ms */ 625#define WSDCF_BASEDELAY 0.010 /* ~ 10ms */
626#define WSDCF_DESCRIPTION "WS/DCF Receiver" 626#define WSDCF_DESCRIPTION "WS/DCF Receiver"
627#define WSDCF_FORMAT "Schmid" 627#define WSDCF_FORMAT "Schmid"
628#define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */ 628#define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */
629#define WSDCF_SPEED (B1200) 629#define WSDCF_SPEED (B1200)
630#define WSDCF_CFLAG (CS8|CREAD|CLOCAL) 630#define WSDCF_CFLAG (CS8|CREAD|CLOCAL)
631#define WSDCF_IFLAG 0 631#define WSDCF_IFLAG 0
632#define WSDCF_OFLAG 0 632#define WSDCF_OFLAG 0
633#define WSDCF_LFLAG 0 633#define WSDCF_LFLAG 0
634#define WSDCF_SAMPLES 5 634#define WSDCF_SAMPLES 5
635#define WSDCF_KEEP 3 635#define WSDCF_KEEP 3
636 636
637/* 637/*
638 * RAW DCF77 - input of DCF marks via RS232 - many variants 638 * RAW DCF77 - input of DCF marks via RS232 - many variants
639 */ 639 */
640#define RAWDCF_FLAGS 0 640#define RAWDCF_FLAGS 0
641#define RAWDCF_ROOTDELAY 0.0 /* 0 */ 641#define RAWDCF_ROOTDELAY 0.0 /* 0 */
642#define RAWDCF_BASEDELAY 0.258 642#define RAWDCF_BASEDELAY 0.258
643#define RAWDCF_FORMAT "RAW DCF77 Timecode" 643#define RAWDCF_FORMAT "RAW DCF77 Timecode"
644#define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */ 644#define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */
645#define RAWDCF_SPEED (B50) 645#define RAWDCF_SPEED (B50)
646#ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */ 646#ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */
647/* somehow doesn't grok PARENB & IGNPAR (mj) */ 647/* somehow doesn't grok PARENB & IGNPAR (mj) */
648# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL) 648# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL)
649#else 649#else
650# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL|PARENB) 650# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL|PARENB)
651#endif 651#endif
652#ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */ 652#ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */
653# define RAWDCF_IFLAG 0 653# define RAWDCF_IFLAG 0
654#else 654#else
655# define RAWDCF_IFLAG (IGNPAR) 655# define RAWDCF_IFLAG (IGNPAR)
656#endif 656#endif
657#define RAWDCF_OFLAG 0 657#define RAWDCF_OFLAG 0
658#define RAWDCF_LFLAG 0 658#define RAWDCF_LFLAG 0
659#define RAWDCF_SAMPLES 20 659#define RAWDCF_SAMPLES 20
660#define RAWDCF_KEEP 12 660#define RAWDCF_KEEP 12
661#define RAWDCF_INIT 0 661#define RAWDCF_INIT 0
662 662
663/* 663/*
664 * RAW DCF variants 664 * RAW DCF variants
665 */ 665 */
666/* 666/*
667 * Conrad receiver 667 * Conrad receiver
668 * 668 *
669 * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad 669 * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
670 * (~40DM - roughly $30 ) followed by a level converter for RS232 670 * (~40DM - roughly $30 ) followed by a level converter for RS232
671 */ 671 */
672#define CONRAD_BASEDELAY 0.292 /* Conrad receiver @ 50 Baud on a Sun */ 672#define CONRAD_BASEDELAY 0.292 /* Conrad receiver @ 50 Baud on a Sun */
673#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)" 673#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
674 674
675/* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */ 675/* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */
676#define GUDE_EMC_USB_V20_SPEED (B4800) 676#define GUDE_EMC_USB_V20_SPEED (B4800)
677#define GUDE_EMC_USB_V20_BASEDELAY 0.425 /* USB serial<->USB converter FTDI232R */ 677#define GUDE_EMC_USB_V20_BASEDELAY 0.425 /* USB serial<->USB converter FTDI232R */
678#define GUDE_EMC_USB_V20_DESCRIPTION "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)" 678#define GUDE_EMC_USB_V20_DESCRIPTION "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)"
679 679
680/* 680/*
681 * TimeBrick receiver 681 * TimeBrick receiver
682 */ 682 */
683#define TIMEBRICK_BASEDELAY 0.210 /* TimeBrick @ 50 Baud on a Sun */ 683#define TIMEBRICK_BASEDELAY 0.210 /* TimeBrick @ 50 Baud on a Sun */
684#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)" 684#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
685 685
686/* 686/*
687 * IGEL:clock receiver 687 * IGEL:clock receiver
688 */ 688 */
689#define IGELCLOCK_BASEDELAY 0.258 /* IGEL:clock receiver */ 689#define IGELCLOCK_BASEDELAY 0.258 /* IGEL:clock receiver */
690#define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)" 690#define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)"
691#define IGELCLOCK_SPEED (B1200) 691#define IGELCLOCK_SPEED (B1200)
692#define IGELCLOCK_CFLAG (CS8|CREAD|HUPCL|CLOCAL) 692#define IGELCLOCK_CFLAG (CS8|CREAD|HUPCL|CLOCAL)
693 693
694/* 694/*
695 * RAWDCF receivers that need to be powered from DTR 695 * RAWDCF receivers that need to be powered from DTR
696 * (like Expert mouse clock) 696 * (like Expert mouse clock)
697 */ 697 */
698static int rawdcf_init_1 (struct parseunit *); 698static int rawdcf_init_1 (struct parseunit *);
699#define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)" 699#define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)"
700#define RAWDCFDTRSET75_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR @ 75 baud)" 700#define RAWDCFDTRSET75_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR @ 75 baud)"
701#define RAWDCFDTRSET_INIT rawdcf_init_1 701#define RAWDCFDTRSET_INIT rawdcf_init_1
702 702
703/* 703/*
704 * RAWDCF receivers that need to be powered from 704 * RAWDCF receivers that need to be powered from
705 * DTR CLR and RTS SET 705 * DTR CLR and RTS SET
706 */ 706 */
707static int rawdcf_init_2 (struct parseunit *); 707static int rawdcf_init_2 (struct parseunit *);
708#define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)" 708#define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)"
709#define RAWDCFDTRCLRRTSSET75_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET @ 75 baud)" 709#define RAWDCFDTRCLRRTSSET75_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET @ 75 baud)"
710#define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2 710#define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2
711 711
712/* 712/*
713 * Trimble GPS receivers (TAIP and TSIP protocols) 713 * Trimble GPS receivers (TAIP and TSIP protocols)
714 */ 714 */
715#ifndef TRIM_POLLRATE 715#ifndef TRIM_POLLRATE
716#define TRIM_POLLRATE 0 /* only true direct polling */ 716#define TRIM_POLLRATE 0 /* only true direct polling */
717#endif 717#endif
718 718
719#define TRIM_TAIPPOLLCMD ">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<" 719#define TRIM_TAIPPOLLCMD ">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<"
720#define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1) 720#define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1)
721 721
722static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE }; 722static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
723static int trimbletaip_init (struct parseunit *); 723static int trimbletaip_init (struct parseunit *);
724static void trimbletaip_event (struct parseunit *, int); 724static void trimbletaip_event (struct parseunit *, int);
725 725
726/* query time & UTC correction data */ 726/* query time & UTC correction data */
727static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX }; 727static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
728 728
729static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) }; 729static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
730static int trimbletsip_init (struct parseunit *); 730static int trimbletsip_init (struct parseunit *);
731static void trimbletsip_end (struct parseunit *); 731static void trimbletsip_end (struct parseunit *);
732static void trimbletsip_message (struct parseunit *, parsetime_t *); 732static void trimbletsip_message (struct parseunit *, parsetime_t *);
733static void trimbletsip_event (struct parseunit *, int); 733static void trimbletsip_event (struct parseunit *, int);
734 734
735#define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */ 735#define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
736#define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME 736#define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME
737 737
738#define TRIMBLETAIP_SPEED (B4800) 738#define TRIMBLETAIP_SPEED (B4800)
739#define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL) 739#define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL)
740#define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON) 740#define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
741#define TRIMBLETAIP_OFLAG (OPOST|ONLCR) 741#define TRIMBLETAIP_OFLAG (OPOST|ONLCR)
742#define TRIMBLETAIP_LFLAG (0) 742#define TRIMBLETAIP_LFLAG (0)
743 743
744#define TRIMBLETSIP_SPEED (B9600) 744#define TRIMBLETSIP_SPEED (B9600)
745#define TRIMBLETSIP_CFLAG (CS8|CLOCAL|CREAD|PARENB|PARODD) 745#define TRIMBLETSIP_CFLAG (CS8|CLOCAL|CREAD|PARENB|PARODD)
746#define TRIMBLETSIP_IFLAG (IGNBRK) 746#define TRIMBLETSIP_IFLAG (IGNBRK)
747#define TRIMBLETSIP_OFLAG (0) 747#define TRIMBLETSIP_OFLAG (0)
748#define TRIMBLETSIP_LFLAG (ICANON) 748#define TRIMBLETSIP_LFLAG (ICANON)
749 749
750#define TRIMBLETSIP_SAMPLES 5 750#define TRIMBLETSIP_SAMPLES 5
751#define TRIMBLETSIP_KEEP 3 751#define TRIMBLETSIP_KEEP 3
752#define TRIMBLETAIP_SAMPLES 5 752#define TRIMBLETAIP_SAMPLES 5
753#define TRIMBLETAIP_KEEP 3 753#define TRIMBLETAIP_KEEP 3
754 754
755#define TRIMBLETAIP_FLAGS (PARSE_F_PPSONSECOND) 755#define TRIMBLETAIP_FLAGS (PARSE_F_PPSONSECOND)
756#define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS) 756#define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS)
757 757
758#define TRIMBLETAIP_POLL poll_dpoll 758#define TRIMBLETAIP_POLL poll_dpoll
759#define TRIMBLETSIP_POLL poll_dpoll 759#define TRIMBLETSIP_POLL poll_dpoll
760 760
761#define TRIMBLETAIP_INIT trimbletaip_init 761#define TRIMBLETAIP_INIT trimbletaip_init
762#define TRIMBLETSIP_INIT trimbletsip_init 762#define TRIMBLETSIP_INIT trimbletsip_init
763 763
764#define TRIMBLETAIP_EVENT trimbletaip_event 764#define TRIMBLETAIP_EVENT trimbletaip_event
765 765
766#define TRIMBLETSIP_EVENT trimbletsip_event 766#define TRIMBLETSIP_EVENT trimbletsip_event
767#define TRIMBLETSIP_MESSAGE trimbletsip_message 767#define TRIMBLETSIP_MESSAGE trimbletsip_message
768 768
769#define TRIMBLETAIP_END 0 769#define TRIMBLETAIP_END 0
770#define TRIMBLETSIP_END trimbletsip_end 770#define TRIMBLETSIP_END trimbletsip_end
771 771
772#define TRIMBLETAIP_DATA ((void *)(&trimbletaip_pollinfo)) 772#define TRIMBLETAIP_DATA ((void *)(&trimbletaip_pollinfo))
773#define TRIMBLETSIP_DATA ((void *)(&trimbletsip_pollinfo)) 773#define TRIMBLETSIP_DATA ((void *)(&trimbletsip_pollinfo))
774 774
775#define TRIMBLETAIP_ID GPS_ID 775#define TRIMBLETAIP_ID GPS_ID
776#define TRIMBLETSIP_ID GPS_ID 776#define TRIMBLETSIP_ID GPS_ID
777 777
778#define TRIMBLETAIP_FORMAT "Trimble TAIP" 778#define TRIMBLETAIP_FORMAT "Trimble TAIP"
779#define TRIMBLETSIP_FORMAT "Trimble TSIP" 779#define TRIMBLETSIP_FORMAT "Trimble TSIP"
780 780
781#define TRIMBLETAIP_ROOTDELAY 0x0 781#define TRIMBLETAIP_ROOTDELAY 0x0
782#define TRIMBLETSIP_ROOTDELAY 0x0 782#define TRIMBLETSIP_ROOTDELAY 0x0
783 783
784#define TRIMBLETAIP_BASEDELAY 0.0 784#define TRIMBLETAIP_BASEDELAY 0.0
785#define TRIMBLETSIP_BASEDELAY 0.020 /* GPS time message latency */ 785#define TRIMBLETSIP_BASEDELAY 0.020 /* GPS time message latency */
786 786
787#define TRIMBLETAIP_DESCRIPTION "Trimble GPS (TAIP) receiver" 787#define TRIMBLETAIP_DESCRIPTION "Trimble GPS (TAIP) receiver"
788#define TRIMBLETSIP_DESCRIPTION "Trimble GPS (TSIP) receiver" 788#define TRIMBLETSIP_DESCRIPTION "Trimble GPS (TSIP) receiver"
789 789
790#define TRIMBLETAIP_MAXUNSYNC 0 790#define TRIMBLETAIP_MAXUNSYNC 0
791#define TRIMBLETSIP_MAXUNSYNC 0 791#define TRIMBLETSIP_MAXUNSYNC 0
792 792
793#define TRIMBLETAIP_EOL '<' 793#define TRIMBLETAIP_EOL '<'
794 794
795/* 795/*
796 * RadioCode Clocks RCC 800 receiver 796 * RadioCode Clocks RCC 800 receiver
797 */ 797 */
798#define RCC_POLLRATE 0 /* only true direct polling */ 798#define RCC_POLLRATE 0 /* only true direct polling */
799#define RCC_POLLCMD "\r" 799#define RCC_POLLCMD "\r"
800#define RCC_CMDSIZE 1 800#define RCC_CMDSIZE 1
801 801
802static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE }; 802static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE };
803#define RCC8000_FLAGS 0 803#define RCC8000_FLAGS 0
804#define RCC8000_POLL poll_dpoll 804#define RCC8000_POLL poll_dpoll
805#define RCC8000_INIT poll_init 805#define RCC8000_INIT poll_init
806#define RCC8000_END 0 806#define RCC8000_END 0
807#define RCC8000_DATA ((void *)(&rcc8000_pollinfo)) 807#define RCC8000_DATA ((void *)(&rcc8000_pollinfo))
808#define RCC8000_ROOTDELAY 0.0 808#define RCC8000_ROOTDELAY 0.0
809#define RCC8000_BASEDELAY 0.0 809#define RCC8000_BASEDELAY 0.0
810#define RCC8000_ID "MSF" 810#define RCC8000_ID "MSF"
811#define RCC8000_DESCRIPTION "RCC 8000 MSF Receiver" 811#define RCC8000_DESCRIPTION "RCC 8000 MSF Receiver"
812#define RCC8000_FORMAT "Radiocode RCC8000" 812#define RCC8000_FORMAT "Radiocode RCC8000"
813#define RCC8000_MAXUNSYNC (60*60) /* should be ok for an hour */ 813#define RCC8000_MAXUNSYNC (60*60) /* should be ok for an hour */
814#define RCC8000_SPEED (B2400) 814#define RCC8000_SPEED (B2400)
815#define RCC8000_CFLAG (CS8|CREAD|CLOCAL) 815#define RCC8000_CFLAG (CS8|CREAD|CLOCAL)
816#define RCC8000_IFLAG (IGNBRK|IGNPAR) 816#define RCC8000_IFLAG (IGNBRK|IGNPAR)
817#define RCC8000_OFLAG 0 817#define RCC8000_OFLAG 0
818#define RCC8000_LFLAG 0 818#define RCC8000_LFLAG 0
819#define RCC8000_SAMPLES 5 819#define RCC8000_SAMPLES 5
820#define RCC8000_KEEP 3 820#define RCC8000_KEEP 3
821 821
822/* 822/*
823 * Hopf Radio clock 6021 Format 823 * Hopf Radio clock 6021 Format
824 * 824 *
825 */ 825 */
826#define HOPF6021_ROOTDELAY 0.0 826#define HOPF6021_ROOTDELAY 0.0
827#define HOPF6021_BASEDELAY 0.0 827#define HOPF6021_BASEDELAY 0.0
828#define HOPF6021_DESCRIPTION "HOPF 6021" 828#define HOPF6021_DESCRIPTION "HOPF 6021"
829#define HOPF6021_FORMAT "hopf Funkuhr 6021" 829#define HOPF6021_FORMAT "hopf Funkuhr 6021"
830#define HOPF6021_MAXUNSYNC (60*60) /* should be ok for an hour */ 830#define HOPF6021_MAXUNSYNC (60*60) /* should be ok for an hour */
831#define HOPF6021_SPEED (B9600) 831#define HOPF6021_SPEED (B9600)
832#define HOPF6021_CFLAG (CS8|CREAD|CLOCAL) 832#define HOPF6021_CFLAG (CS8|CREAD|CLOCAL)
833#define HOPF6021_IFLAG (IGNBRK|ISTRIP) 833#define HOPF6021_IFLAG (IGNBRK|ISTRIP)
834#define HOPF6021_OFLAG 0 834#define HOPF6021_OFLAG 0
835#define HOPF6021_LFLAG 0 835#define HOPF6021_LFLAG 0
836#define HOPF6021_FLAGS 0 836#define HOPF6021_FLAGS 0
837#define HOPF6021_SAMPLES 5 837#define HOPF6021_SAMPLES 5
838#define HOPF6021_KEEP 3 838#define HOPF6021_KEEP 3
839 839
840/* 840/*
841 * Diem's Computime Radio Clock Receiver 841 * Diem's Computime Radio Clock Receiver
842 */ 842 */
843#define COMPUTIME_FLAGS 0 843#define COMPUTIME_FLAGS 0
844#define COMPUTIME_ROOTDELAY 0.0 844#define COMPUTIME_ROOTDELAY 0.0
845#define COMPUTIME_BASEDELAY 0.0 845#define COMPUTIME_BASEDELAY 0.0
846#define COMPUTIME_ID DCF_ID 846#define COMPUTIME_ID DCF_ID
847#define COMPUTIME_DESCRIPTION "Diem's Computime receiver" 847#define COMPUTIME_DESCRIPTION "Diem's Computime receiver"
848#define COMPUTIME_FORMAT "Diem's Computime Radio Clock" 848#define COMPUTIME_FORMAT "Diem's Computime Radio Clock"
849#define COMPUTIME_TYPE DCF_TYPE 849#define COMPUTIME_TYPE DCF_TYPE
850#define COMPUTIME_MAXUNSYNC (60*60) /* only trust clock for 1 hour */ 850#define COMPUTIME_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
851#define COMPUTIME_SPEED (B9600) 851#define COMPUTIME_SPEED (B9600)
852#define COMPUTIME_CFLAG (CSTOPB|CS7|CREAD|CLOCAL) 852#define COMPUTIME_CFLAG (CSTOPB|CS7|CREAD|CLOCAL)
853#define COMPUTIME_IFLAG (IGNBRK|IGNPAR|ISTRIP) 853#define COMPUTIME_IFLAG (IGNBRK|IGNPAR|ISTRIP)
854#define COMPUTIME_OFLAG 0 854#define COMPUTIME_OFLAG 0
855#define COMPUTIME_LFLAG 0 855#define COMPUTIME_LFLAG 0
856#define COMPUTIME_SAMPLES 5 856#define COMPUTIME_SAMPLES 5
857#define COMPUTIME_KEEP 3 857#define COMPUTIME_KEEP 3
858 858
859/* 859/*
860 * Varitext Radio Clock Receiver 860 * Varitext Radio Clock Receiver
861 */ 861 */
862#define VARITEXT_FLAGS 0 862#define VARITEXT_FLAGS 0
863#define VARITEXT_ROOTDELAY 0.0 863#define VARITEXT_ROOTDELAY 0.0
864#define VARITEXT_BASEDELAY 0.0 864#define VARITEXT_BASEDELAY 0.0
865#define VARITEXT_ID "MSF" 865#define VARITEXT_ID "MSF"
866#define VARITEXT_DESCRIPTION "Varitext receiver" 866#define VARITEXT_DESCRIPTION "Varitext receiver"
867#define VARITEXT_FORMAT "Varitext Radio Clock" 867#define VARITEXT_FORMAT "Varitext Radio Clock"
868#define VARITEXT_TYPE DCF_TYPE 868#define VARITEXT_TYPE DCF_TYPE
869#define VARITEXT_MAXUNSYNC (60*60) /* only trust clock for 1 hour */ 869#define VARITEXT_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
870#define VARITEXT_SPEED (B9600) 870#define VARITEXT_SPEED (B9600)
871#define VARITEXT_CFLAG (CS7|CREAD|CLOCAL|PARENB|PARODD) 871#define VARITEXT_CFLAG (CS7|CREAD|CLOCAL|PARENB|PARODD)
872#define VARITEXT_IFLAG (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/ 872#define VARITEXT_IFLAG (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/
873#define VARITEXT_OFLAG 0 873#define VARITEXT_OFLAG 0
874#define VARITEXT_LFLAG 0 874#define VARITEXT_LFLAG 0
875#define VARITEXT_SAMPLES 32 875#define VARITEXT_SAMPLES 32
876#define VARITEXT_KEEP 20 876#define VARITEXT_KEEP 20
877 877
878/* 878/*
879 * SEL240x Satellite Sychronized Clock 879 * SEL240x Satellite Sychronized Clock
880 */ 880 */
881#define SEL240X_POLLRATE 0 /* only true direct polling */ 881#define SEL240X_POLLRATE 0 /* only true direct polling */
882#define SEL240X_POLLCMD "BUB8" 882#define SEL240X_POLLCMD "BUB8"
883#define SEL240X_CMDSIZE 4 883#define SEL240X_CMDSIZE 4
884 884
885static poll_info_t sel240x_pollinfo = { SEL240X_POLLRATE, 885static poll_info_t sel240x_pollinfo = { SEL240X_POLLRATE,
886 SEL240X_POLLCMD, 886 SEL240X_POLLCMD,
887 SEL240X_CMDSIZE }; 887 SEL240X_CMDSIZE };
888#define SEL240X_FLAGS (PARSE_F_PPSONSECOND) 888#define SEL240X_FLAGS (PARSE_F_PPSONSECOND)
889#define SEL240X_POLL poll_dpoll 889#define SEL240X_POLL poll_dpoll
890#define SEL240X_INIT poll_init 890#define SEL240X_INIT poll_init
891#define SEL240X_END 0 891#define SEL240X_END 0
892#define SEL240X_DATA ((void *)(&sel240x_pollinfo)) 892#define SEL240X_DATA ((void *)(&sel240x_pollinfo))
893#define SEL240X_ROOTDELAY 0.0 893#define SEL240X_ROOTDELAY 0.0
894#define SEL240X_BASEDELAY 0.0 894#define SEL240X_BASEDELAY 0.0
895#define SEL240X_ID GPS_ID 895#define SEL240X_ID GPS_ID
896#define SEL240X_DESCRIPTION "SEL240x Satellite Synchronized Clock" 896#define SEL240X_DESCRIPTION "SEL240x Satellite Synchronized Clock"
897#define SEL240X_FORMAT "SEL B8" 897#define SEL240X_FORMAT "SEL B8"
898#define SEL240X_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours */ 898#define SEL240X_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours */
899#define SEL240X_SPEED (B9600) 899#define SEL240X_SPEED (B9600)
900#define SEL240X_CFLAG (CS8|CREAD|CLOCAL) 900#define SEL240X_CFLAG (CS8|CREAD|CLOCAL)
901#define SEL240X_IFLAG (IGNBRK|IGNPAR) 901#define SEL240X_IFLAG (IGNBRK|IGNPAR)
902#define SEL240X_OFLAG (0) 902#define SEL240X_OFLAG (0)
903#define SEL240X_LFLAG (0) 903#define SEL240X_LFLAG (0)
904#define SEL240X_SAMPLES 5 904#define SEL240X_SAMPLES 5
905#define SEL240X_KEEP 3 905#define SEL240X_KEEP 3
906 906
907static struct parse_clockinfo 907static struct parse_clockinfo
908{ 908{
909 u_long cl_flags; /* operation flags (PPS interpretation, trust handling) */ 909 u_long cl_flags; /* operation flags (PPS interpretation, trust handling) */
910 void (*cl_poll) (struct parseunit *); /* active poll routine */ 910 void (*cl_poll) (struct parseunit *); /* active poll routine */
911 int (*cl_init) (struct parseunit *); /* active poll init routine */ 911 int (*cl_init) (struct parseunit *); /* active poll init routine */
912 void (*cl_event) (struct parseunit *, int); /* special event handling (e.g. reset clock) */ 912 void (*cl_event) (struct parseunit *, int); /* special event handling (e.g. reset clock) */
913 void (*cl_end) (struct parseunit *); /* active poll end routine */ 913 void (*cl_end) (struct parseunit *); /* active poll end routine */
914 void (*cl_message) (struct parseunit *, parsetime_t *); /* process a lower layer message */ 914 void (*cl_message) (struct parseunit *, parsetime_t *); /* process a lower layer message */
915 void *cl_data; /* local data area for "poll" mechanism */ 915 void *cl_data; /* local data area for "poll" mechanism */
916 double cl_rootdelay; /* rootdelay */ 916 double cl_rootdelay; /* rootdelay */
917 double cl_basedelay; /* current offset by which the RS232 917 double cl_basedelay; /* current offset by which the RS232
918 time code is delayed from the actual time */ 918 time code is delayed from the actual time */
919 const char *cl_id; /* ID code */ 919 const char *cl_id; /* ID code */
920 const char *cl_description; /* device name */ 920 const char *cl_description; /* device name */
921 const char *cl_format; /* fixed format */ 921 const char *cl_format; /* fixed format */
922 u_char cl_type; /* clock type (ntp control) */ 922 u_char cl_type; /* clock type (ntp control) */
923 u_long cl_maxunsync; /* time to trust oscillator after losing synch */ 923 u_long cl_maxunsync; /* time to trust oscillator after losing synch */
924 u_long cl_speed; /* terminal input & output baudrate */ 924 u_long cl_speed; /* terminal input & output baudrate */
925 u_long cl_cflag; /* terminal control flags */ 925 u_long cl_cflag; /* terminal control flags */
926 u_long cl_iflag; /* terminal input flags */ 926 u_long cl_iflag; /* terminal input flags */
927 u_long cl_oflag; /* terminal output flags */ 927 u_long cl_oflag; /* terminal output flags */
928 u_long cl_lflag; /* terminal local flags */ 928 u_long cl_lflag; /* terminal local flags */
929 u_long cl_samples; /* samples for median filter */ 929 u_long cl_samples; /* samples for median filter */
930 u_long cl_keep; /* samples for median filter to keep */ 930 u_long cl_keep; /* samples for median filter to keep */
931} parse_clockinfo[] = 931} parse_clockinfo[] =
932{ 932{
933 { /* mode 0 */ 933 { /* mode 0 */
934 MBG_FLAGS, 934 MBG_FLAGS,
935 NO_POLL, 935 NO_POLL,
936 NO_INIT, 936 NO_INIT,
937 NO_EVENT, 937 NO_EVENT,
938 NO_END, 938 NO_END,
939 NO_MESSAGE, 939 NO_MESSAGE,
940 NO_LCLDATA, 940 NO_LCLDATA,
941 DCFPZF535_ROOTDELAY, 941 DCFPZF535_ROOTDELAY,
942 DCFPZF535_BASEDELAY, 942 DCFPZF535_BASEDELAY,
943 DCF_P_ID, 943 DCF_P_ID,
944 DCFPZF535_DESCRIPTION, 944 DCFPZF535_DESCRIPTION,
945 DCFPZF535_FORMAT, 945 DCFPZF535_FORMAT,
946 DCF_TYPE, 946 DCF_TYPE,
947 DCFPZF535_MAXUNSYNC, 947 DCFPZF535_MAXUNSYNC,
948 DCFPZF535_SPEED, 948 DCFPZF535_SPEED,
949 DCFPZF535_CFLAG, 949 DCFPZF535_CFLAG,
950 DCFPZF535_IFLAG, 950 DCFPZF535_IFLAG,
951 DCFPZF535_OFLAG, 951 DCFPZF535_OFLAG,
952 DCFPZF535_LFLAG, 952 DCFPZF535_LFLAG,
953 DCFPZF535_SAMPLES, 953 DCFPZF535_SAMPLES,
954 DCFPZF535_KEEP 954 DCFPZF535_KEEP
955 }, 955 },
956 { /* mode 1 */ 956 { /* mode 1 */
957 MBG_FLAGS, 957 MBG_FLAGS,
958 NO_POLL, 958 NO_POLL,
959 NO_INIT, 959 NO_INIT,
960 NO_EVENT, 960 NO_EVENT,
961 NO_END, 961 NO_END,
962 NO_MESSAGE, 962 NO_MESSAGE,
963 NO_LCLDATA, 963 NO_LCLDATA,
964 DCFPZF535OCXO_ROOTDELAY, 964 DCFPZF535OCXO_ROOTDELAY,
965 DCFPZF535OCXO_BASEDELAY, 965 DCFPZF535OCXO_BASEDELAY,
966 DCF_P_ID, 966 DCF_P_ID,
967 DCFPZF535OCXO_DESCRIPTION, 967 DCFPZF535OCXO_DESCRIPTION,
968 DCFPZF535OCXO_FORMAT, 968 DCFPZF535OCXO_FORMAT,
969 DCF_TYPE, 969 DCF_TYPE,
970 DCFPZF535OCXO_MAXUNSYNC, 970 DCFPZF535OCXO_MAXUNSYNC,
971 DCFPZF535OCXO_SPEED, 971 DCFPZF535OCXO_SPEED,
972 DCFPZF535OCXO_CFLAG, 972 DCFPZF535OCXO_CFLAG,
973 DCFPZF535OCXO_IFLAG, 973 DCFPZF535OCXO_IFLAG,
974 DCFPZF535OCXO_OFLAG, 974 DCFPZF535OCXO_OFLAG,
975 DCFPZF535OCXO_LFLAG, 975 DCFPZF535OCXO_LFLAG,
976 DCFPZF535OCXO_SAMPLES, 976 DCFPZF535OCXO_SAMPLES,
977 DCFPZF535OCXO_KEEP 977 DCFPZF535OCXO_KEEP
978 }, 978 },
979 { /* mode 2 */ 979 { /* mode 2 */
980 MBG_FLAGS, 980 MBG_FLAGS,
981 NO_POLL, 981 NO_POLL,
982 NO_INIT, 982 NO_INIT,
983 NO_EVENT, 983 NO_EVENT,
984 NO_END, 984 NO_END,
985 NO_MESSAGE, 985 NO_MESSAGE,
986 NO_LCLDATA, 986 NO_LCLDATA,
987 DCFUA31_ROOTDELAY, 987 DCFUA31_ROOTDELAY,
988 DCFUA31_BASEDELAY, 988 DCFUA31_BASEDELAY,
989 DCF_A_ID, 989 DCF_A_ID,
990 DCFUA31_DESCRIPTION, 990 DCFUA31_DESCRIPTION,
991 DCFUA31_FORMAT, 991 DCFUA31_FORMAT,
992 DCF_TYPE, 992 DCF_TYPE,
993 DCFUA31_MAXUNSYNC, 993 DCFUA31_MAXUNSYNC,
994 DCFUA31_SPEED, 994 DCFUA31_SPEED,
995 DCFUA31_CFLAG, 995 DCFUA31_CFLAG,
996 DCFUA31_IFLAG, 996 DCFUA31_IFLAG,
997 DCFUA31_OFLAG, 997 DCFUA31_OFLAG,
998 DCFUA31_LFLAG, 998 DCFUA31_LFLAG,
999 DCFUA31_SAMPLES, 999 DCFUA31_SAMPLES,
1000 DCFUA31_KEEP 1000 DCFUA31_KEEP
@@ -3291,1999 +3291,1999 @@ parse_start( @@ -3291,1999 +3291,1999 @@ parse_start(
3291 { 3291 {
3292 msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit); 3292 msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
3293 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */ 3293 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3294 return 0; /* well, ok - special initialisation broke */ 3294 return 0; /* well, ok - special initialisation broke */
3295 } 3295 }
3296 3296
3297 /* 3297 /*
3298 * get rid of all IO accumulated so far 3298 * get rid of all IO accumulated so far
3299 */ 3299 */
3300#ifdef HAVE_TERMIOS 3300#ifdef HAVE_TERMIOS
3301 (void) tcflush(parse->generic->io.fd, TCIOFLUSH); 3301 (void) tcflush(parse->generic->io.fd, TCIOFLUSH);
3302#else 3302#else
3303#if defined(TCFLSH) && defined(TCIOFLUSH) 3303#if defined(TCFLSH) && defined(TCIOFLUSH)
3304 { 3304 {
3305 int flshcmd = TCIOFLUSH; 3305 int flshcmd = TCIOFLUSH;
3306 3306
3307 (void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd); 3307 (void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
3308 } 3308 }
3309#endif 3309#endif
3310#endif 3310#endif
3311 3311
3312 /* 3312 /*
3313 * try to do any special initializations 3313 * try to do any special initializations
3314 */ 3314 */
3315 if (parse->parse_type->cl_init) 3315 if (parse->parse_type->cl_init)
3316 { 3316 {
3317 if (parse->parse_type->cl_init(parse)) 3317 if (parse->parse_type->cl_init(parse))
3318 { 3318 {
3319 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */ 3319 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3320 return 0; /* well, ok - special initialisation broke */ 3320 return 0; /* well, ok - special initialisation broke */
3321 } 3321 }
3322 } 3322 }
3323 3323
3324 /* 3324 /*
3325 * Insert in async io device list. 3325 * Insert in async io device list.
3326 */ 3326 */
3327 if (!io_addclock(&parse->generic->io)) 3327 if (!io_addclock(&parse->generic->io))
3328 { 3328 {
3329 msyslog(LOG_ERR, 3329 msyslog(LOG_ERR,
3330 "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev); 3330 "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
3331 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */ 3331 parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3332 return 0; 3332 return 0;
3333 } 3333 }
3334 3334
3335 /* 3335 /*
3336 * print out configuration 3336 * print out configuration
3337 */ 3337 */
3338 NLOG(NLOG_CLOCKINFO) 3338 NLOG(NLOG_CLOCKINFO)
3339 { 3339 {
3340 /* conditional if clause for conditional syslog */ 3340 /* conditional if clause for conditional syslog */
3341 msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added", 3341 msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
3342 CLK_UNIT(parse->peer), 3342 CLK_UNIT(parse->peer),
3343 parse->parse_type->cl_description, parsedev, 3343 parse->parse_type->cl_description, parsedev,
3344 (parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev); 3344 (parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
3345 3345
3346 msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d", 3346 msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
3347 CLK_UNIT(parse->peer), 3347 CLK_UNIT(parse->peer),
3348 parse->peer->stratum, 3348 parse->peer->stratum,
3349 l_mktime(parse->maxunsync), parse->peer->precision); 3349 l_mktime(parse->maxunsync), parse->peer->precision);
3350 3350
3351 msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling", 3351 msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
3352 CLK_UNIT(parse->peer), 3352 CLK_UNIT(parse->peer),
3353 parse->parse_type->cl_rootdelay, 3353 parse->parse_type->cl_rootdelay,
3354 parse->generic->fudgetime1, 3354 parse->generic->fudgetime1,
3355 parse->ppsphaseadjust, 3355 parse->ppsphaseadjust,
3356 parse->binding->bd_description); 3356 parse->binding->bd_description);
3357 3357
3358 msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer), 3358 msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
3359 parse->parse_type->cl_format); 3359 parse->parse_type->cl_format);
3360 msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer), 3360 msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
3361 CLK_PPS(parse->peer) ? "" : "NO ", 3361 CLK_PPS(parse->peer) ? "" : "NO ",
3362 CLK_PPS(parse->peer) ? 3362 CLK_PPS(parse->peer) ?
3363#ifdef PPS_METHOD 3363#ifdef PPS_METHOD
3364 " (implementation " PPS_METHOD ")" 3364 " (implementation " PPS_METHOD ")"
3365#else 3365#else
3366 "" 3366 ""
3367#endif 3367#endif
3368 : "" 3368 : ""
3369 ); 3369 );
3370 } 3370 }
3371 3371
3372 return 1; 3372 return 1;
3373} 3373}
3374 3374
3375/*-------------------------------------------------- 3375/*--------------------------------------------------
3376 * parse_ctl - process changes on flags/time values 3376 * parse_ctl - process changes on flags/time values
3377 */ 3377 */
3378static void 3378static void
3379parse_ctl( 3379parse_ctl(
3380 struct parseunit *parse, 3380 struct parseunit *parse,
3381 const struct refclockstat *in 3381 const struct refclockstat *in
3382 ) 3382 )
3383{ 3383{
3384 if (in) 3384 if (in)
3385 { 3385 {
3386 if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4)) 3386 if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
3387 { 3387 {
3388 u_char mask = CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4; 3388 u_char mask = CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4;
3389 parse->flags = (parse->flags & (u_char)(~mask)) | (in->flags & mask); 3389 parse->flags = (parse->flags & (u_char)(~mask)) | (in->flags & mask);
3390#if defined(HAVE_PPSAPI) 3390#if defined(HAVE_PPSAPI)
3391 if (CLK_PPS(parse->peer)) 3391 if (CLK_PPS(parse->peer))
3392 { 3392 {
3393 parse_ppsapi(parse); 3393 parse_ppsapi(parse);
3394 } 3394 }
3395#endif 3395#endif
3396 } 3396 }
3397 3397
3398 if (in->haveflags & CLK_HAVETIME1) 3398 if (in->haveflags & CLK_HAVETIME1)
3399 { 3399 {
3400 parse->generic->fudgetime1 = in->fudgetime1; 3400 parse->generic->fudgetime1 = in->fudgetime1;
3401 msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s", 3401 msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
3402 CLK_UNIT(parse->peer), 3402 CLK_UNIT(parse->peer),
3403 parse->generic->fudgetime1); 3403 parse->generic->fudgetime1);
3404 } 3404 }
3405 3405
3406 if (in->haveflags & CLK_HAVETIME2) 3406 if (in->haveflags & CLK_HAVETIME2)
3407 { 3407 {
3408 parse->generic->fudgetime2 = in->fudgetime2; 3408 parse->generic->fudgetime2 = in->fudgetime2;
3409 if (parse->flags & PARSE_TRUSTTIME) 3409 if (parse->flags & PARSE_TRUSTTIME)
3410 { 3410 {
3411 parse->maxunsync = (u_long)ABS(in->fudgetime2); 3411 parse->maxunsync = (u_long)ABS(in->fudgetime2);
3412 msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s", 3412 msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
3413 CLK_UNIT(parse->peer), 3413 CLK_UNIT(parse->peer),
3414 l_mktime(parse->maxunsync)); 3414 l_mktime(parse->maxunsync));
3415 } 3415 }
3416 else 3416 else
3417 { 3417 {
3418 parse->ppsphaseadjust = in->fudgetime2; 3418 parse->ppsphaseadjust = in->fudgetime2;
3419 msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s", 3419 msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
3420 CLK_UNIT(parse->peer), 3420 CLK_UNIT(parse->peer),
3421 parse->ppsphaseadjust); 3421 parse->ppsphaseadjust);
3422#if defined(HAVE_PPSAPI) 3422#if defined(HAVE_PPSAPI)
3423 if (CLK_PPS(parse->peer)) 3423 if (CLK_PPS(parse->peer))
3424 { 3424 {
3425 parse_ppsapi(parse); 3425 parse_ppsapi(parse);
3426 } 3426 }
3427#endif 3427#endif
3428 } 3428 }
3429 } 3429 }
3430 3430
3431 parse->generic->fudgeminjitter = in->fudgeminjitter; 3431 parse->generic->fudgeminjitter = in->fudgeminjitter;
3432 } 3432 }
3433} 3433}
3434 3434
3435/*-------------------------------------------------- 3435/*--------------------------------------------------
3436 * parse_poll - called by the transmit procedure 3436 * parse_poll - called by the transmit procedure
3437 */ 3437 */
3438static void 3438static void
3439parse_poll( 3439parse_poll(
3440 int unit, 3440 int unit,
3441 struct peer *peer 3441 struct peer *peer
3442 ) 3442 )
3443{ 3443{
3444 struct parseunit *parse = peer->procptr->unitptr; 3444 struct parseunit *parse = peer->procptr->unitptr;
3445 3445
3446 if (peer != parse->peer) 3446 if (peer != parse->peer)
3447 { 3447 {
3448 msyslog(LOG_ERR, 3448 msyslog(LOG_ERR,
3449 "PARSE receiver #%d: poll: INTERNAL: peer incorrect", 3449 "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
3450 unit); 3450 unit);
3451 return; 3451 return;
3452 } 3452 }
3453 3453
3454 /* 3454 /*
3455 * Update clock stat counters 3455 * Update clock stat counters
3456 */ 3456 */
3457 parse->generic->polls++; 3457 parse->generic->polls++;
3458 3458
3459 if (parse->pollneeddata && 3459 if (parse->pollneeddata &&
3460 ((int)(current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll))))) 3460 ((int)(current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
3461 { 3461 {
3462 /* 3462 /*
3463 * start worrying when exceeding a poll inteval 3463 * start worrying when exceeding a poll inteval
3464 * bad news - didn't get a response last time 3464 * bad news - didn't get a response last time
3465 */ 3465 */
3466 parse->lastmissed = current_time; 3466 parse->lastmissed = current_time;
3467 parse_event(parse, CEVNT_TIMEOUT); 3467 parse_event(parse, CEVNT_TIMEOUT);
3468 3468
3469 ERR(ERR_NODATA) 3469 ERR(ERR_NODATA)
3470 msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer)); 3470 msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
3471 } 3471 }
3472 3472
3473 /* 3473 /*
3474 * we just mark that we want the next sample for the clock filter 3474 * we just mark that we want the next sample for the clock filter
3475 */ 3475 */
3476 parse->pollneeddata = current_time; 3476 parse->pollneeddata = current_time;
3477 3477
3478 if (parse->parse_type->cl_poll) 3478 if (parse->parse_type->cl_poll)
3479 { 3479 {
3480 parse->parse_type->cl_poll(parse); 3480 parse->parse_type->cl_poll(parse);
3481 } 3481 }
3482 3482
3483 cparse_statistics(parse); 3483 cparse_statistics(parse);
3484 3484
3485 return; 3485 return;
3486} 3486}
3487 3487
3488#define LEN_STATES 300 /* length of state string */ 3488#define LEN_STATES 300 /* length of state string */
3489 3489
3490/*-------------------------------------------------- 3490/*--------------------------------------------------
3491 * parse_control - set fudge factors, return statistics 3491 * parse_control - set fudge factors, return statistics
3492 */ 3492 */
3493static void 3493static void
3494parse_control( 3494parse_control(
3495 int unit, 3495 int unit,
3496 const struct refclockstat *in, 3496 const struct refclockstat *in,
3497 struct refclockstat *out, 3497 struct refclockstat *out,
3498 struct peer *peer 3498 struct peer *peer
3499 ) 3499 )
3500{ 3500{
3501 struct parseunit *parse = peer->procptr->unitptr; 3501 struct parseunit *parse = peer->procptr->unitptr;
3502 parsectl_t tmpctl; 3502 parsectl_t tmpctl;
3503 3503
3504 static char outstatus[400]; /* status output buffer */ 3504 static char outstatus[400]; /* status output buffer */
3505 3505
3506 if (out) 3506 if (out)
3507 { 3507 {
3508 out->lencode = 0; 3508 out->lencode = 0;
3509 out->p_lastcode = 0; 3509 out->p_lastcode = 0;
3510 out->kv_list = (struct ctl_var *)0; 3510 out->kv_list = (struct ctl_var *)0;
3511 } 3511 }
3512 3512
3513 if (!parse || !parse->peer) 3513 if (!parse || !parse->peer)
3514 { 3514 {
3515 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)", 3515 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
3516 unit); 3516 unit);
3517 return; 3517 return;
3518 } 3518 }
3519 3519
3520 unit = CLK_UNIT(parse->peer); 3520 unit = CLK_UNIT(parse->peer);
3521 3521
3522 /* 3522 /*
3523 * handle changes 3523 * handle changes
3524 */ 3524 */
3525 parse_ctl(parse, in); 3525 parse_ctl(parse, in);
3526 3526
3527 /* 3527 /*
3528 * supply data 3528 * supply data
3529 */ 3529 */
3530 if (out) 3530 if (out)
3531 { 3531 {
3532 u_long sum = 0; 3532 u_long sum = 0;
3533 char *tt, *start; 3533 char *tt, *start;
3534 int i; 3534 int i;
3535 3535
3536 outstatus[0] = '\0'; 3536 outstatus[0] = '\0';
3537 3537
3538 out->type = REFCLK_PARSE; 3538 out->type = REFCLK_PARSE;
3539 3539
3540 /* 3540 /*
3541 * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1 3541 * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
3542 */ 3542 */
3543 parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust; 3543 parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
3544 3544
3545 /* 3545 /*
3546 * figure out skew between PPS and RS232 - just for informational 3546 * figure out skew between PPS and RS232 - just for informational
3547 * purposes 3547 * purposes
3548 */ 3548 */
3549 if (PARSE_SYNC(parse->timedata.parse_state)) 3549 if (PARSE_SYNC(parse->timedata.parse_state))
3550 { 3550 {
3551 if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state)) 3551 if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
3552 { 3552 {
3553 l_fp off; 3553 l_fp off;
3554 3554
3555 /* 3555 /*
3556 * we have a PPS and RS232 signal - calculate the skew 3556 * we have a PPS and RS232 signal - calculate the skew
3557 * WARNING: assumes on TIMECODE == PULSE (timecode after pulse) 3557 * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
3558 */ 3558 */
3559 off = parse->timedata.parse_stime.fp; 3559 off = parse->timedata.parse_stime.fp;
3560 L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */ 3560 L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
3561 tt = add_var(&out->kv_list, 80, RO); 3561 tt = add_var(&out->kv_list, 80, RO);
3562 snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6)); 3562 snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
3563 } 3563 }
3564 } 3564 }
3565 3565
3566 if (PARSE_PPS(parse->timedata.parse_state)) 3566 if (PARSE_PPS(parse->timedata.parse_state))
3567 { 3567 {
3568 tt = add_var(&out->kv_list, 80, RO|DEF); 3568 tt = add_var(&out->kv_list, 80, RO|DEF);
3569 snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp)); 3569 snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
3570 } 3570 }
3571 3571
3572 start = tt = add_var(&out->kv_list, 128, RO|DEF); 3572 start = tt = add_var(&out->kv_list, 128, RO|DEF);
3573 tt = ap(start, 128, tt, "refclock_time=\""); 3573 tt = ap(start, 128, tt, "refclock_time=\"");
3574 3574
3575 if (parse->timedata.parse_time.fp.l_ui == 0) 3575 if (parse->timedata.parse_time.fp.l_ui == 0)
3576 { 3576 {
3577 tt = ap(start, 128, tt, "<UNDEFINED>\""); 3577 tt = ap(start, 128, tt, "<UNDEFINED>\"");
3578 } 3578 }
3579 else 3579 else
3580 { 3580 {
3581 tt = ap(start, 128, tt, "%s\"", 3581 tt = ap(start, 128, tt, "%s\"",
3582 gmprettydate(&parse->timedata.parse_time.fp)); 3582 gmprettydate(&parse->timedata.parse_time.fp));
3583 } 3583 }
3584 3584
3585 if (!PARSE_GETTIMECODE(parse, &tmpctl)) 3585 if (!PARSE_GETTIMECODE(parse, &tmpctl))
3586 { 3586 {
3587 ERR(ERR_INTERNAL) 3587 ERR(ERR_INTERNAL)
3588 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit); 3588 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
3589 } 3589 }
3590 else 3590 else
3591 { 3591 {
3592 start = tt = add_var(&out->kv_list, 512, RO|DEF); 3592 start = tt = add_var(&out->kv_list, 512, RO|DEF);
3593 tt = ap(start, 512, tt, "refclock_status=\""); 3593 tt = ap(start, 512, tt, "refclock_status=\"");
3594 3594
3595 /* 3595 /*
3596 * copy PPS flags from last read transaction (informational only) 3596 * copy PPS flags from last read transaction (informational only)
3597 */ 3597 */
3598 tmpctl.parsegettc.parse_state |= parse->timedata.parse_state & 3598 tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
3599 (PARSEB_PPS|PARSEB_S_PPS); 3599 (PARSEB_PPS|PARSEB_S_PPS);
3600 3600
3601 (void)parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512)); 3601 (void)parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
3602 3602
3603 tt += strlen(tt); 3603 tt += strlen(tt);
3604 3604
3605 tt = ap(start, 512, tt, "\""); 3605 tt = ap(start, 512, tt, "\"");
3606 3606
3607 if (tmpctl.parsegettc.parse_count) 3607 if (tmpctl.parsegettc.parse_count)
3608 mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1), 3608 mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
3609 tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count)); 3609 tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
3610 3610
3611 } 3611 }
3612 3612
3613 tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format; 3613 tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
3614 3614
3615 if (!PARSE_GETFMT(parse, &tmpctl)) 3615 if (!PARSE_GETFMT(parse, &tmpctl))
3616 { 3616 {
3617 ERR(ERR_INTERNAL) 3617 ERR(ERR_INTERNAL)
3618 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit); 3618 msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
3619 } 3619 }
3620 else 3620 else
3621 { 3621 {
3622 int count = tmpctl.parseformat.parse_count; 3622 int count = tmpctl.parseformat.parse_count;
3623 if (count) 3623 if (count)
3624 --count; 3624 --count;
3625 3625
3626 start = tt = add_var(&out->kv_list, 80, RO|DEF); 3626 start = tt = add_var(&out->kv_list, 80, RO|DEF);
3627 tt = ap(start, 80, tt, "refclock_format=\""); 3627 tt = ap(start, 80, tt, "refclock_format=\"");
3628 3628
3629 if (count > 0) { 3629 if (count > 0) {
3630 tt = ap(start, 80, tt, "%*.*s", 3630 tt = ap(start, 80, tt, "%*.*s",
3631 count, 3631 count,
3632 count, 3632 count,
3633 tmpctl.parseformat.parse_buffer); 3633 tmpctl.parseformat.parse_buffer);
3634 } 3634 }
3635 3635
3636 tt = ap(start, 80, tt, "\""); 3636 tt = ap(start, 80, tt, "\"");
3637 } 3637 }
3638 3638
3639 /* 3639 /*
3640 * gather state statistics 3640 * gather state statistics
3641 */ 3641 */
3642 3642
3643 start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF); 3643 start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
3644 tt = ap(start, LEN_STATES, tt, "refclock_states=\""); 3644 tt = ap(start, LEN_STATES, tt, "refclock_states=\"");
3645 3645
3646 for (i = 0; i <= CEVNT_MAX; i++) 3646 for (i = 0; i <= CEVNT_MAX; i++)
3647 { 3647 {
3648 u_long s_time; 3648 u_long s_time;
3649 u_long d = current_time - parse->generic->timestarted; 3649 u_long d = current_time - parse->generic->timestarted;
3650 u_long percent; 3650 u_long percent;
3651 3651
3652 percent = s_time = PARSE_STATETIME(parse, i); 3652 percent = s_time = PARSE_STATETIME(parse, i);
3653 3653
3654 while (((u_long)(~0) / 10000) < percent) 3654 while (((u_long)(~0) / 10000) < percent)
3655 { 3655 {
3656 percent /= 10; 3656 percent /= 10;
3657 d /= 10; 3657 d /= 10;
3658 } 3658 }
3659 3659
3660 if (d) 3660 if (d)
3661 percent = (percent * 10000) / d; 3661 percent = (percent * 10000) / d;
3662 else 3662 else
3663 percent = 10000; 3663 percent = 10000;
3664 3664
3665 if (s_time) 3665 if (s_time)
3666 { 3666 {
3667 char item[80]; 3667 char item[80];
3668 int count; 3668 int count;
3669 3669
3670 snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)", 3670 snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
3671 sum ? "; " : "", 3671 sum ? "; " : "",
3672 (parse->generic->currentstatus == i) ? "*" : "", 3672 (parse->generic->currentstatus == i) ? "*" : "",
3673 clockstatus((unsigned int)i), 3673 clockstatus((unsigned int)i),
3674 l_mktime(s_time), 3674 l_mktime(s_time),
3675 (int)(percent / 100), (int)(percent % 100)); 3675 (int)(percent / 100), (int)(percent % 100));
3676 if ((count = (int) strlen(item)) < (LEN_STATES - 40 - (tt - start))) 3676 if ((count = (int) strlen(item)) < (LEN_STATES - 40 - (tt - start)))
3677 { 3677 {
3678 tt = ap(start, LEN_STATES, tt, 3678 tt = ap(start, LEN_STATES, tt,
3679 "%s", item); 3679 "%s", item);
3680 } 3680 }
3681 sum += s_time; 3681 sum += s_time;
3682 } 3682 }
3683 } 3683 }
3684 3684
3685 ap(start, LEN_STATES, tt, "; running time: %s\"", l_mktime(sum)); 3685 ap(start, LEN_STATES, tt, "; running time: %s\"", l_mktime(sum));
3686 3686
3687 tt = add_var(&out->kv_list, 32, RO); 3687 tt = add_var(&out->kv_list, 32, RO);
3688 snprintf(tt, 32, "refclock_id=\"%s\"", parse->parse_type->cl_id); 3688 snprintf(tt, 32, "refclock_id=\"%s\"", parse->parse_type->cl_id);
3689 3689
3690 tt = add_var(&out->kv_list, 80, RO); 3690 tt = add_var(&out->kv_list, 80, RO);
3691 snprintf(tt, 80, "refclock_iomode=\"%s\"", parse->binding->bd_description); 3691 snprintf(tt, 80, "refclock_iomode=\"%s\"", parse->binding->bd_description);
3692 3692
3693 tt = add_var(&out->kv_list, 128, RO); 3693 tt = add_var(&out->kv_list, 128, RO);
3694 snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid); 3694 snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
3695 3695
3696 { 3696 {
3697 struct ctl_var *k; 3697 struct ctl_var *k;
3698 3698
3699 k = parse->kv; 3699 k = parse->kv;
3700 while (k && !(k->flags & EOV)) 3700 while (k && !(k->flags & EOV))
3701 { 3701 {
3702 set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags); 3702 set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
3703 k++; 3703 k++;
3704 } 3704 }
3705 } 3705 }
3706 3706
3707 out->lencode = (u_short) strlen(outstatus); 3707 out->lencode = (u_short) strlen(outstatus);
3708 out->p_lastcode = outstatus; 3708 out->p_lastcode = outstatus;
3709 } 3709 }
3710} 3710}
3711 3711
3712/**=========================================================================== 3712/**===========================================================================
3713 ** processing routines 3713 ** processing routines
3714 **/ 3714 **/
3715 3715
3716/*-------------------------------------------------- 3716/*--------------------------------------------------
3717 * event handling - note that nominal events will also be posted 3717 * event handling - note that nominal events will also be posted
3718 * keep track of state dwelling times 3718 * keep track of state dwelling times
3719 */ 3719 */
3720static void 3720static void
3721parse_event( 3721parse_event(
3722 struct parseunit *parse, 3722 struct parseunit *parse,
3723 int event 3723 int event
3724 ) 3724 )
3725{ 3725{
3726 if (parse->generic->currentstatus != (u_char) event) 3726 if (parse->generic->currentstatus != (u_char) event)
3727 { 3727 {
3728 parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange; 3728 parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
3729 parse->lastchange = current_time; 3729 parse->lastchange = current_time;
3730 3730
3731 if (parse->parse_type->cl_event) 3731 if (parse->parse_type->cl_event)
3732 parse->parse_type->cl_event(parse, event); 3732 parse->parse_type->cl_event(parse, event);
3733 3733
3734 if (event == CEVNT_NOMINAL) 3734 if (event == CEVNT_NOMINAL)
3735 { 3735 {
3736 NLOG(NLOG_CLOCKSTATUS) 3736 NLOG(NLOG_CLOCKSTATUS)
3737 msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED", 3737 msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
3738 CLK_UNIT(parse->peer)); 3738 CLK_UNIT(parse->peer));
3739 } 3739 }
3740 3740
3741 refclock_report(parse->peer, event); 3741 refclock_report(parse->peer, event);
3742 } 3742 }
3743} 3743}
3744 3744
3745/*-------------------------------------------------- 3745/*--------------------------------------------------
3746 * process a PARSE time sample 3746 * process a PARSE time sample
3747 */ 3747 */
3748static void 3748static void
3749parse_process( 3749parse_process(
3750 struct parseunit *parse, 3750 struct parseunit *parse,
3751 parsetime_t *parsetime 3751 parsetime_t *parsetime
3752 ) 3752 )
3753{ 3753{
3754 l_fp off, rectime, reftime; 3754 l_fp off, rectime, reftime;
3755 double fudge; 3755 double fudge;
3756 3756
3757 /* silence warning: 'off.Ul_i.Xl_i' may be used uninitialized in this function */ 3757 /* silence warning: 'off.Ul_i.Xl_i' may be used uninitialized in this function */
3758 ZERO(off); 3758 ZERO(off);
3759 3759
3760 /* 3760 /*
3761 * check for changes in conversion status 3761 * check for changes in conversion status
3762 * (only one for each new status !) 3762 * (only one for each new status !)
3763 */ 3763 */
3764 if (((parsetime->parse_status & CVT_MASK) != CVT_OK) && 3764 if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
3765 ((parsetime->parse_status & CVT_MASK) != CVT_NONE) && 3765 ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
3766 (parse->timedata.parse_status != parsetime->parse_status)) 3766 (parse->timedata.parse_status != parsetime->parse_status))
3767 { 3767 {
3768 char buffer[400]; 3768 char buffer[400];
3769 3769
3770 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ 3770 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3771 msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"", 3771 msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
3772 CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer))); 3772 CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
3773 3773
3774 if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL) 3774 if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
3775 { 3775 {
3776 /* 3776 /*
3777 * tell more about the story - list time code 3777 * tell more about the story - list time code
3778 * there is a slight change for a race condition and 3778 * there is a slight change for a race condition and
3779 * the time code might be overwritten by the next packet 3779 * the time code might be overwritten by the next packet
3780 */ 3780 */
3781 parsectl_t tmpctl; 3781 parsectl_t tmpctl;
3782 3782
3783 if (!PARSE_GETTIMECODE(parse, &tmpctl)) 3783 if (!PARSE_GETTIMECODE(parse, &tmpctl))
3784 { 3784 {
3785 ERR(ERR_INTERNAL) 3785 ERR(ERR_INTERNAL)
3786 msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer)); 3786 msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
3787 } 3787 }
3788 else 3788 else
3789 { 3789 {
3790 unsigned int count = tmpctl.parsegettc.parse_count; 3790 unsigned int count = tmpctl.parsegettc.parse_count;
3791 if (count) 3791 if (count)
3792 --count; 3792 --count;
3793 ERR(ERR_BADDATA) 3793 ERR(ERR_BADDATA)
3794 msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)", 3794 msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
3795 CLK_UNIT(parse->peer), 3795 CLK_UNIT(parse->peer),
3796 mkascii(buffer, sizeof(buffer), 3796 mkascii(buffer, sizeof(buffer),
3797 tmpctl.parsegettc.parse_buffer, count)); 3797 tmpctl.parsegettc.parse_buffer, count));
3798 } 3798 }
3799 /* copy status to show only changes in case of failures */ 3799 /* copy status to show only changes in case of failures */
3800 parse->timedata.parse_status = parsetime->parse_status; 3800 parse->timedata.parse_status = parsetime->parse_status;
3801 } 3801 }
3802 } 3802 }
3803 3803
3804 /* 3804 /*
3805 * examine status and post appropriate events 3805 * examine status and post appropriate events
3806 */ 3806 */
3807 if ((parsetime->parse_status & CVT_MASK) != CVT_OK) 3807 if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
3808 { 3808 {
3809 /* 3809 /*
3810 * got bad data - tell the rest of the system 3810 * got bad data - tell the rest of the system
3811 */ 3811 */
3812 switch (parsetime->parse_status & CVT_MASK) 3812 switch (parsetime->parse_status & CVT_MASK)
3813 { 3813 {
3814 case CVT_NONE: 3814 case CVT_NONE:
3815 if ((parsetime->parse_status & CVT_ADDITIONAL) && 3815 if ((parsetime->parse_status & CVT_ADDITIONAL) &&
3816 parse->parse_type->cl_message) 3816 parse->parse_type->cl_message)
3817 parse->parse_type->cl_message(parse, parsetime); 3817 parse->parse_type->cl_message(parse, parsetime);
3818 /* 3818 /*
3819 * save PPS information that comes piggyback 3819 * save PPS information that comes piggyback
3820 */ 3820 */
3821 if (PARSE_PPS(parsetime->parse_state)) 3821 if (PARSE_PPS(parsetime->parse_state))
3822 { 3822 {
3823 parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS; 3823 parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
3824 parse->timedata.parse_ptime = parsetime->parse_ptime; 3824 parse->timedata.parse_ptime = parsetime->parse_ptime;
3825 } 3825 }
3826 break; /* well, still waiting - timeout is handled at higher levels */ 3826 break; /* well, still waiting - timeout is handled at higher levels */
3827 3827
3828 case CVT_FAIL: 3828 case CVT_FAIL:
3829 if (parsetime->parse_status & CVT_BADFMT) 3829 if (parsetime->parse_status & CVT_BADFMT)
3830 { 3830 {
3831 parse_event(parse, CEVNT_BADREPLY); 3831 parse_event(parse, CEVNT_BADREPLY);
3832 } 3832 }
3833 else 3833 else
3834 if (parsetime->parse_status & CVT_BADDATE) 3834 if (parsetime->parse_status & CVT_BADDATE)
3835 { 3835 {
3836 parse_event(parse, CEVNT_BADDATE); 3836 parse_event(parse, CEVNT_BADDATE);
3837 } 3837 }
3838 else 3838 else
3839 if (parsetime->parse_status & CVT_BADTIME) 3839 if (parsetime->parse_status & CVT_BADTIME)
3840 { 3840 {
3841 parse_event(parse, CEVNT_BADTIME); 3841 parse_event(parse, CEVNT_BADTIME);
3842 } 3842 }
3843 else 3843 else
3844 { 3844 {
3845 parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */ 3845 parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
3846 } 3846 }
3847 } 3847 }
3848 return; /* skip the rest - useless */ 3848 return; /* skip the rest - useless */
3849 } 3849 }
3850 3850
3851 /* 3851 /*
3852 * check for format changes 3852 * check for format changes
3853 * (in case somebody has swapped clocks 8-) 3853 * (in case somebody has swapped clocks 8-)
3854 */ 3854 */
3855 if (parse->lastformat != parsetime->parse_format) 3855 if (parse->lastformat != parsetime->parse_format)
3856 { 3856 {
3857 parsectl_t tmpctl; 3857 parsectl_t tmpctl;
3858 3858
3859 tmpctl.parseformat.parse_format = parsetime->parse_format; 3859 tmpctl.parseformat.parse_format = parsetime->parse_format;
3860 3860
3861 if (!PARSE_GETFMT(parse, &tmpctl)) 3861 if (!PARSE_GETFMT(parse, &tmpctl))
3862 { 3862 {
3863 ERR(ERR_INTERNAL) 3863 ERR(ERR_INTERNAL)
3864 msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer)); 3864 msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
3865 } 3865 }
3866 else 3866 else
3867 { 3867 {
3868 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ 3868 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3869 msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"", 3869 msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
3870 CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer); 3870 CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer);
3871 } 3871 }
3872 parse->lastformat = parsetime->parse_format; 3872 parse->lastformat = parsetime->parse_format;
3873 } 3873 }
3874 3874
3875 /* 3875 /*
3876 * now, any changes ? 3876 * now, any changes ?
3877 */ 3877 */
3878 if ((parse->timedata.parse_state ^ parsetime->parse_state) & 3878 if ((parse->timedata.parse_state ^ parsetime->parse_state) &
3879 ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS)) 3879 ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
3880 { 3880 {
3881 char tmp1[200]; 3881 char tmp1[200];
3882 char tmp2[200]; 3882 char tmp2[200];
3883 /* 3883 /*
3884 * something happend - except for PPS events 3884 * something happend - except for PPS events
3885 */ 3885 */
3886 3886
3887 (void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1)); 3887 (void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
3888 (void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2)); 3888 (void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
3889 3889
3890 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ 3890 NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3891 msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s", 3891 msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
3892 CLK_UNIT(parse->peer), tmp2, tmp1); 3892 CLK_UNIT(parse->peer), tmp2, tmp1);
3893 } 3893 }
3894 3894
3895 /* 3895 /*
3896 * carry on PPS information if still usable 3896 * carry on PPS information if still usable
3897 */ 3897 */
3898 if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state)) 3898 if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
3899 { 3899 {
3900 parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS; 3900 parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
3901 parsetime->parse_ptime = parse->timedata.parse_ptime; 3901 parsetime->parse_ptime = parse->timedata.parse_ptime;
3902 } 3902 }
3903 3903
3904 /* 3904 /*
3905 * remember for future 3905 * remember for future
3906 */ 3906 */
3907 parse->timedata = *parsetime; 3907 parse->timedata = *parsetime;
3908 3908
3909 /* 3909 /*
3910 * check to see, whether the clock did a complete powerup or lost PZF signal 3910 * check to see, whether the clock did a complete powerup or lost PZF signal
3911 * and post correct events for current condition 3911 * and post correct events for current condition
3912 */ 3912 */
3913 if (PARSE_POWERUP(parsetime->parse_state)) 3913 if (PARSE_POWERUP(parsetime->parse_state))
3914 { 3914 {
3915 /* 3915 /*
3916 * this is bad, as we have completely lost synchronisation 3916 * this is bad, as we have completely lost synchronisation
3917 * well this is a problem with the receiver here 3917 * well this is a problem with the receiver here
3918 * for PARSE Meinberg DCF77 receivers the lost synchronisation 3918 * for PARSE Meinberg DCF77 receivers the lost synchronisation
3919 * is true as it is the powerup state and the time is taken 3919 * is true as it is the powerup state and the time is taken
3920 * from a crude real time clock chip 3920 * from a crude real time clock chip
3921 * for the PZF/GPS series this is only partly true, as 3921 * for the PZF/GPS series this is only partly true, as
3922 * PARSE_POWERUP only means that the pseudo random 3922 * PARSE_POWERUP only means that the pseudo random
3923 * phase shift sequence cannot be found. this is only 3923 * phase shift sequence cannot be found. this is only
3924 * bad, if we have never seen the clock in the SYNC 3924 * bad, if we have never seen the clock in the SYNC
3925 * state, where the PHASE and EPOCH are correct. 3925 * state, where the PHASE and EPOCH are correct.
3926 * for reporting events the above business does not 3926 * for reporting events the above business does not
3927 * really matter, but we can use the time code 3927 * really matter, but we can use the time code
3928 * even in the POWERUP state after having seen 3928 * even in the POWERUP state after having seen
3929 * the clock in the synchronized state (PZF class 3929 * the clock in the synchronized state (PZF class
3930 * receivers) unless we have had a telegram disruption 3930 * receivers) unless we have had a telegram disruption
3931 * after having seen the clock in the SYNC state. we 3931 * after having seen the clock in the SYNC state. we
3932 * thus require having seen the clock in SYNC state 3932 * thus require having seen the clock in SYNC state
3933 * *after* having missed telegrams (noresponse) from 3933 * *after* having missed telegrams (noresponse) from
3934 * the clock. one problem remains: we might use erroneously 3934 * the clock. one problem remains: we might use erroneously
3935 * POWERUP data if the disruption is shorter than 1 polling 3935 * POWERUP data if the disruption is shorter than 1 polling
3936 * interval. fortunately powerdowns last usually longer than 64 3936 * interval. fortunately powerdowns last usually longer than 64
3937 * seconds and the receiver is at least 2 minutes in the 3937 * seconds and the receiver is at least 2 minutes in the
3938 * POWERUP or NOSYNC state before switching to SYNC 3938 * POWERUP or NOSYNC state before switching to SYNC
3939 * for GPS receivers this can mean antenna problems and other causes. 3939 * for GPS receivers this can mean antenna problems and other causes.
3940 * the additional grace period can be enables by a clock 3940 * the additional grace period can be enables by a clock
3941 * mode having the PARSE_F_POWERUPTRUST flag in cl_flag set. 3941 * mode having the PARSE_F_POWERUPTRUST flag in cl_flag set.
3942 */ 3942 */
3943 parse_event(parse, CEVNT_FAULT); 3943 parse_event(parse, CEVNT_FAULT);
3944 NLOG(NLOG_CLOCKSTATUS) 3944 NLOG(NLOG_CLOCKSTATUS)
3945 ERR(ERR_BADSTATUS) 3945 ERR(ERR_BADSTATUS)
3946 msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED/RECEIVER PROBLEMS", 3946 msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED/RECEIVER PROBLEMS",
3947 CLK_UNIT(parse->peer)); 3947 CLK_UNIT(parse->peer));
3948 } 3948 }
3949 else 3949 else
3950 { 3950 {
3951 /* 3951 /*
3952 * we have two states left 3952 * we have two states left
3953 * 3953 *
3954 * SYNC: 3954 * SYNC:
3955 * this state means that the EPOCH (timecode) and PHASE 3955 * this state means that the EPOCH (timecode) and PHASE
3956 * information has be read correctly (at least two 3956 * information has be read correctly (at least two
3957 * successive PARSE timecodes were received correctly) 3957 * successive PARSE timecodes were received correctly)
3958 * this is the best possible state - full trust 3958 * this is the best possible state - full trust
3959 * 3959 *
3960 * NOSYNC: 3960 * NOSYNC:
3961 * The clock should be on phase with respect to the second 3961 * The clock should be on phase with respect to the second
3962 * signal, but the timecode has not been received correctly within 3962 * signal, but the timecode has not been received correctly within
3963 * at least the last two minutes. this is a sort of half baked state 3963 * at least the last two minutes. this is a sort of half baked state
3964 * for PARSE Meinberg DCF77 clocks this is bad news (clock running 3964 * for PARSE Meinberg DCF77 clocks this is bad news (clock running
3965 * without timecode confirmation) 3965 * without timecode confirmation)
3966 * PZF 535 has also no time confirmation, but the phase should be 3966 * PZF 535 has also no time confirmation, but the phase should be
3967 * very precise as the PZF signal can be decoded 3967 * very precise as the PZF signal can be decoded
3968 */ 3968 */
3969 3969
3970 if (PARSE_SYNC(parsetime->parse_state)) 3970 if (PARSE_SYNC(parsetime->parse_state))
3971 { 3971 {
3972 /* 3972 /*
3973 * currently completely synchronized - best possible state 3973 * currently completely synchronized - best possible state
3974 */ 3974 */
3975 parse->lastsync = current_time; 3975 parse->lastsync = current_time;
3976 clear_err(parse, ERR_BADSTATUS); 3976 clear_err(parse, ERR_BADSTATUS);
3977 } 3977 }
3978 else 3978 else
3979 { 3979 {
3980 /* 3980 /*
3981 * we have had some problems receiving the time code 3981 * we have had some problems receiving the time code
3982 */ 3982 */
3983 parse_event(parse, CEVNT_PROP); 3983 parse_event(parse, CEVNT_PROP);
3984 NLOG(NLOG_CLOCKSTATUS) 3984 NLOG(NLOG_CLOCKSTATUS)
3985 ERR(ERR_BADSTATUS) 3985 ERR(ERR_BADSTATUS)
3986 msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED", 3986 msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
3987 CLK_UNIT(parse->peer)); 3987 CLK_UNIT(parse->peer));
3988 } 3988 }
3989 } 3989 }
3990 3990
3991 fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */ 3991 fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
3992 3992
3993 if (PARSE_TIMECODE(parsetime->parse_state)) 3993 if (PARSE_TIMECODE(parsetime->parse_state))
3994 { 3994 {
3995 rectime = parsetime->parse_stime.fp; 3995 rectime = parsetime->parse_stime.fp;
3996 off = reftime = parsetime->parse_time.fp; 3996 off = reftime = parsetime->parse_time.fp;
3997 3997
3998 L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */ 3998 L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
3999 3999
4000#ifdef DEBUG 4000#ifdef DEBUG
4001 if (debug > 3) 4001 if (debug > 3)
4002 printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n", 4002 printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
4003 CLK_UNIT(parse->peer), 4003 CLK_UNIT(parse->peer),
4004 prettydate(&reftime), 4004 prettydate(&reftime),
4005 prettydate(&rectime), 4005 prettydate(&rectime),
4006 lfptoa(&off,6)); 4006 lfptoa(&off,6));
4007#endif 4007#endif
4008 } 4008 }
4009 4009
4010 if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer)) 4010 if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
4011 { 4011 {
4012 l_fp offset; 4012 l_fp offset;
4013 double ppsphaseadjust = parse->ppsphaseadjust; 4013 double ppsphaseadjust = parse->ppsphaseadjust;
4014 4014
4015#ifdef HAVE_PPSAPI 4015#ifdef HAVE_PPSAPI
4016 /* 4016 /*
4017 * set fudge = 0.0 if already included in PPS time stamps 4017 * set fudge = 0.0 if already included in PPS time stamps
4018 */ 4018 */
4019 if (parse->atom.pps_params.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT)) 4019 if (parse->atom.pps_params.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
4020 { 4020 {
4021 ppsphaseadjust = 0.0; 4021 ppsphaseadjust = 0.0;
4022 } 4022 }
4023#endif 4023#endif
4024 4024
4025 /* 4025 /*
4026 * we have a PPS signal - much better than the RS232 stuff (we hope) 4026 * we have a PPS signal - much better than the RS232 stuff (we hope)
4027 */ 4027 */
4028 offset = parsetime->parse_ptime.fp; 4028 offset = parsetime->parse_ptime.fp;
4029 4029
4030#ifdef DEBUG 4030#ifdef DEBUG
4031 if (debug > 3) 4031 if (debug > 3)
4032 printf("PARSE receiver #%d: PPStime %s\n", 4032 printf("PARSE receiver #%d: PPStime %s\n",
4033 CLK_UNIT(parse->peer), 4033 CLK_UNIT(parse->peer),
4034 prettydate(&offset)); 4034 prettydate(&offset));
4035#endif 4035#endif
4036 if (PARSE_TIMECODE(parsetime->parse_state)) 4036 if (PARSE_TIMECODE(parsetime->parse_state))
4037 { 4037 {
4038 if (M_ISGEQ(off.l_i, off.l_uf, -1, 0x80000000) && 4038 if (M_ISGEQ(off.l_i, off.l_uf, -1, 0x80000000) &&
4039 M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_uf)) 4039 M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_uf))
4040 { 4040 {
4041 fudge = ppsphaseadjust; /* pick PPS fudge factor */ 4041 fudge = ppsphaseadjust; /* pick PPS fudge factor */
4042 4042
4043 /* 4043 /*
4044 * RS232 offsets within [-0.5..0.5[ - take PPS offsets 4044 * RS232 offsets within [-0.5..0.5[ - take PPS offsets
4045 */ 4045 */
4046 4046
4047 if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND) 4047 if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
4048 { 4048 {
4049 reftime = off = offset; 4049 reftime = off = offset;
4050 if (reftime.l_uf & 0x80000000) 4050 if (reftime.l_uf & 0x80000000)
4051 reftime.l_ui++; 4051 reftime.l_ui++;
4052 reftime.l_uf = 0; 4052 reftime.l_uf = 0;
4053 4053
4054 4054
4055 /* 4055 /*
4056 * implied on second offset 4056 * implied on second offset
4057 */ 4057 */
4058 off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */ 4058 off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
4059 off.l_i = (off.l_uf & 0x80000000) ? -1 : 0; /* sign extend */ 4059 off.l_i = (off.l_uf & 0x80000000) ? -1 : 0; /* sign extend */
4060 } 4060 }
4061 else 4061 else
4062 { 4062 {
4063 /* 4063 /*
4064 * time code describes pulse 4064 * time code describes pulse
4065 */ 4065 */
4066 reftime = off = parsetime->parse_time.fp; 4066 reftime = off = parsetime->parse_time.fp;
4067 4067
4068 L_SUB(&off, &offset); /* true offset */ 4068 L_SUB(&off, &offset); /* true offset */
4069 } 4069 }
4070 } 4070 }
4071 /* 4071 /*
4072 * take RS232 offset when PPS when out of bounds 4072 * take RS232 offset when PPS when out of bounds
4073 */ 4073 */
4074 } 4074 }
4075 else 4075 else
4076 { 4076 {
4077 fudge = ppsphaseadjust; /* pick PPS fudge factor */ 4077 fudge = ppsphaseadjust; /* pick PPS fudge factor */
4078 /* 4078 /*
4079 * Well, no time code to guide us - assume on second pulse 4079 * Well, no time code to guide us - assume on second pulse
4080 * and pray, that we are within [-0.5..0.5[ 4080 * and pray, that we are within [-0.5..0.5[
4081 */ 4081 */
4082 off = offset; 4082 off = offset;
4083 reftime = offset; 4083 reftime = offset;
4084 if (reftime.l_uf & 0x80000000) 4084 if (reftime.l_uf & 0x80000000)
4085 reftime.l_ui++; 4085 reftime.l_ui++;
4086 reftime.l_uf = 0; 4086 reftime.l_uf = 0;
4087 /* 4087 /*
4088 * implied on second offset 4088 * implied on second offset
4089 */ 4089 */
4090 off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */ 4090 off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
4091 off.l_i = (off.l_uf & 0x80000000) ? -1 : 0; /* sign extend */ 4091 off.l_i = (off.l_uf & 0x80000000) ? -1 : 0; /* sign extend */
4092 } 4092 }
4093 } 4093 }
4094 else 4094 else
4095 { 4095 {
4096 if (!PARSE_TIMECODE(parsetime->parse_state)) 4096 if (!PARSE_TIMECODE(parsetime->parse_state))
4097 { 4097 {
4098 /* 4098 /*
4099 * Well, no PPS, no TIMECODE, no more work ... 4099 * Well, no PPS, no TIMECODE, no more work ...
4100 */ 4100 */
4101 if ((parsetime->parse_status & CVT_ADDITIONAL) && 4101 if ((parsetime->parse_status & CVT_ADDITIONAL) &&
4102 parse->parse_type->cl_message) 4102 parse->parse_type->cl_message)
4103 parse->parse_type->cl_message(parse, parsetime); 4103 parse->parse_type->cl_message(parse, parsetime);
4104 return; 4104 return;
4105 } 4105 }
4106 } 4106 }
4107 4107
4108#ifdef DEBUG 4108#ifdef DEBUG
4109 if (debug > 3) 4109 if (debug > 3)
4110 printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n", 4110 printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
4111 CLK_UNIT(parse->peer), 4111 CLK_UNIT(parse->peer),
4112 prettydate(&reftime), 4112 prettydate(&reftime),
4113 prettydate(&rectime), 4113 prettydate(&rectime),
4114 lfptoa(&off,6)); 4114 lfptoa(&off,6));
4115#endif 4115#endif
4116 4116
4117 4117
4118 rectime = reftime; 4118 rectime = reftime;
4119 L_SUB(&rectime, &off); /* just to keep the ntp interface happy */ 4119 L_SUB(&rectime, &off); /* just to keep the ntp interface happy */
4120 4120
4121#ifdef DEBUG 4121#ifdef DEBUG
4122 if (debug > 3) 4122 if (debug > 3)
4123 printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n", 4123 printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
4124 CLK_UNIT(parse->peer), 4124 CLK_UNIT(parse->peer),
4125 prettydate(&reftime), 4125 prettydate(&reftime),
4126 prettydate(&rectime)); 4126 prettydate(&rectime));
4127#endif 4127#endif
4128 4128
4129 if ((parsetime->parse_status & CVT_ADDITIONAL) && 4129 if ((parsetime->parse_status & CVT_ADDITIONAL) &&
4130 parse->parse_type->cl_message) 4130 parse->parse_type->cl_message)
4131 parse->parse_type->cl_message(parse, parsetime); 4131 parse->parse_type->cl_message(parse, parsetime);
4132 4132
4133 if (PARSE_SYNC(parsetime->parse_state)) 4133 if (PARSE_SYNC(parsetime->parse_state))
4134 { 4134 {
4135 /* 4135 /*
4136 * log OK status 4136 * log OK status
4137 */ 4137 */
4138 parse_event(parse, CEVNT_NOMINAL); 4138 parse_event(parse, CEVNT_NOMINAL);
4139 } 4139 }
4140 4140
4141 clear_err(parse, ERR_BADIO); 4141 clear_err(parse, ERR_BADIO);
4142 clear_err(parse, ERR_BADDATA); 4142 clear_err(parse, ERR_BADDATA);
4143 clear_err(parse, ERR_NODATA); 4143 clear_err(parse, ERR_NODATA);
4144 clear_err(parse, ERR_INTERNAL); 4144 clear_err(parse, ERR_INTERNAL);
4145 4145
4146 /* 4146 /*
4147 * and now stick it into the clock machine 4147 * and now stick it into the clock machine
4148 * samples are only valid iff lastsync is not too old and 4148 * samples are only valid iff lastsync is not too old and
4149 * we have seen the clock in sync at least once 4149 * we have seen the clock in sync at least once
4150 * after the last time we didn't see an expected data telegram 4150 * after the last time we didn't see an expected data telegram
4151 * at startup being not in sync is also bad just like 4151 * at startup being not in sync is also bad just like
4152 * POWERUP state unless PARSE_F_POWERUPTRUST is set 4152 * POWERUP state unless PARSE_F_POWERUPTRUST is set
4153 * see the clock states section above for more reasoning 4153 * see the clock states section above for more reasoning
4154 */ 4154 */
4155 if (((current_time - parse->lastsync) > parse->maxunsync) || 4155 if (((current_time - parse->lastsync) > parse->maxunsync) ||
4156 (parse->lastsync < parse->lastmissed) || 4156 (parse->lastsync < parse->lastmissed) ||
4157 ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) || 4157 ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
4158 (((parse->parse_type->cl_flags & PARSE_F_POWERUPTRUST) == 0) && 4158 (((parse->parse_type->cl_flags & PARSE_F_POWERUPTRUST) == 0) &&
4159 PARSE_POWERUP(parsetime->parse_state))) 4159 PARSE_POWERUP(parsetime->parse_state)))
4160 { 4160 {
4161 parse->generic->leap = LEAP_NOTINSYNC; 4161 parse->generic->leap = LEAP_NOTINSYNC;
4162 parse->lastsync = 0; /* wait for full sync again */ 4162 parse->lastsync = 0; /* wait for full sync again */
4163 } 4163 }
4164 else 4164 else
4165 { 4165 {
4166 if (PARSE_LEAPADD(parsetime->parse_state)) 4166 if (PARSE_LEAPADD(parsetime->parse_state))
4167 { 4167 {
4168 /* 4168 /*
4169 * we pick this state also for time code that pass leap warnings 4169 * we pick this state also for time code that pass leap warnings
4170 * without direction information (as earth is currently slowing 4170 * without direction information (as earth is currently slowing
4171 * down). 4171 * down).
4172 */ 4172 */
4173 parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND; 4173 parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
4174 } 4174 }
4175 else 4175 else
4176 if (PARSE_LEAPDEL(parsetime->parse_state)) 4176 if (PARSE_LEAPDEL(parsetime->parse_state))
4177 { 4177 {
4178 parse->generic->leap = LEAP_DELSECOND; 4178 parse->generic->leap = LEAP_DELSECOND;
4179 } 4179 }
4180 else 4180 else
4181 { 4181 {
4182 parse->generic->leap = LEAP_NOWARNING; 4182 parse->generic->leap = LEAP_NOWARNING;
4183 } 4183 }
4184 } 4184 }
4185 4185
4186 if (parse->generic->leap != LEAP_NOTINSYNC) 4186 if (parse->generic->leap != LEAP_NOTINSYNC)
4187 { 4187 {
4188 /* 4188 /*
4189 * only good/trusted samples are interesting 4189 * only good/trusted samples are interesting
4190 */ 4190 */
4191#ifdef DEBUG 4191#ifdef DEBUG
4192 if (debug > 2) 4192 if (debug > 2)
4193 { 4193 {
4194 printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n", 4194 printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
4195 CLK_UNIT(parse->peer), 4195 CLK_UNIT(parse->peer),
4196 prettydate(&reftime), 4196 prettydate(&reftime),
4197 prettydate(&rectime), 4197 prettydate(&rectime),
4198 fudge); 4198 fudge);
4199 } 4199 }
4200#endif 4200#endif
4201 parse->generic->lastref = reftime; 4201 parse->generic->lastref = reftime;
4202 4202
4203 refclock_process_offset(parse->generic, reftime, rectime, fudge); 4203 refclock_process_offset(parse->generic, reftime, rectime, fudge);
4204 4204
4205#ifdef HAVE_PPSAPI 4205#ifdef HAVE_PPSAPI
4206 /* 4206 /*
4207 * pass PPS information on to PPS clock 4207 * pass PPS information on to PPS clock
4208 */ 4208 */
4209 if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer)) 4209 if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
4210 { 4210 {
4211 parse->peer->flags |= (FLAG_PPS | FLAG_TSTAMP_PPS); 4211 parse->peer->flags |= (FLAG_PPS | FLAG_TSTAMP_PPS);
4212 parse_hardpps(parse, PARSE_HARDPPS_ENABLE); 4212 parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
4213 } 4213 }
4214#endif 4214#endif
4215 } else { 4215 } else {
4216 parse_hardpps(parse, PARSE_HARDPPS_DISABLE); 4216 parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
4217 parse->peer->flags &= ~(FLAG_PPS | FLAG_TSTAMP_PPS); 4217 parse->peer->flags &= ~(FLAG_PPS | FLAG_TSTAMP_PPS);
4218 } 4218 }
4219 4219
4220 /* 4220 /*
4221 * ready, unless the machine wants a sample or 4221 * ready, unless the machine wants a sample or
4222 * we are in fast startup mode (peer->dist > MAXDISTANCE) 4222 * we are in fast startup mode (peer->dist > MAXDISTANCE)
4223 */ 4223 */
4224 if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE) 4224 if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
4225 return; 4225 return;
4226 4226
4227 parse->pollneeddata = 0; 4227 parse->pollneeddata = 0;
4228 4228
4229 parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS); 4229 parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
4230 4230
4231 refclock_receive(parse->peer); 4231 refclock_receive(parse->peer);
4232} 4232}
4233 4233
4234/**=========================================================================== 4234/**===========================================================================
4235 ** special code for special clocks 4235 ** special code for special clocks
4236 **/ 4236 **/
4237 4237
4238static void 4238static void
4239mk_utcinfo( 4239mk_utcinfo(
4240 char *t, /* pointer to the output string buffer */ 4240 char *t, /* pointer to the output string buffer */
4241 uint16_t wnt, 4241 uint16_t wnt,
4242 uint16_t wnlsf, 4242 uint16_t wnlsf,
4243 int dn, 4243 int dn,
4244 int dtls, 4244 int dtls,
4245 int dtlsf, 4245 int dtlsf,
4246 int size /* size of the output string buffer */ 4246 int size /* size of the output string buffer */
4247 ) 4247 )
4248{ 4248{
4249 /* 4249 /*
4250 * The week number transmitted by the GPS satellites for the leap date 4250 * The week number transmitted by the GPS satellites for the leap date
4251 * is truncated to 8 bits only. If the nearest leap second date is off 4251 * is truncated to 8 bits only. If the nearest leap second date is off
4252 * the current date by more than +/- 128 weeks then conversion to a 4252 * the current date by more than +/- 128 weeks then conversion to a
4253 * calendar date is ambiguous. On the other hand, if a leap second is 4253 * calendar date is ambiguous. On the other hand, if a leap second is
4254 * currently being announced (i.e. dtlsf != dtls) then the week number 4254 * currently being announced (i.e. dtlsf != dtls) then the week number
4255 * wnlsf is close enough, and we can unambiguously determine the date 4255 * wnlsf is close enough, and we can unambiguously determine the date
4256 * for which the leap second is scheduled. 4256 * for which the leap second is scheduled.
4257 */ 4257 */
4258 if ( dtlsf != dtls ) 4258 if ( dtlsf != dtls )
4259 { 4259 {
4260 time_t t_ls; 4260 time_t t_ls;
4261 struct tm *tm; 4261 struct tm *tm;
4262 int nc; 4262 int nc;
4263 4263
4264 wnlsf = basedate_expand_gpsweek(wnlsf); 4264 wnlsf = basedate_expand_gpsweek(wnlsf);
4265 /* 'wnt' not used here: would need the same treatment as 'wnlsf */ 4265 /* 'wnt' not used here: would need the same treatment as 'wnlsf */
4266 4266
4267 t_ls = (time_t) wnlsf * SECSPERWEEK 4267 t_ls = (time_t) wnlsf * SECSPERWEEK
4268 + (time_t) dn * SECSPERDAY 4268 + (time_t) dn * SECSPERDAY
4269 + GPS_SEC_BIAS - 1; 4269 + GPS_SEC_BIAS - 1;
4270 4270
4271 tm = gmtime( &t_ls ); 4271 tm = gmtime( &t_ls );
4272 if (tm == NULL) /* gmtime() failed */ 4272 if (tm == NULL) /* gmtime() failed */
4273 { 4273 {
4274 snprintf( t, size, "** (gmtime() failed in mk_utcinfo())" ); 4274 snprintf( t, size, "** (gmtime() failed in mk_utcinfo())" );
4275 return; 4275 return;
4276 } 4276 }
4277 4277
4278 nc = snprintf( t, size, "UTC offset transition from %is to %is due to leap second %s", 4278 nc = snprintf( t, size, "UTC offset transition from %is to %is due to leap second %s",
4279 dtls, dtlsf, ( dtls < dtlsf ) ? "insertion" : "deletion" ); 4279 dtls, dtlsf, ( dtls < dtlsf ) ? "insertion" : "deletion" );
4280 if (nc < 0) 4280 if (nc < 0)
4281 nc = strlen(t); 4281 nc = strlen(t);
4282 else if (nc > size) 4282 else if (nc > size)
4283 nc = size; 4283 nc = size;
4284  4284
4285 snprintf( t + nc, size - nc, " at UTC midnight at the end of %s, %04i-%02i-%02i", 4285 snprintf( t + nc, size - nc, " at UTC midnight at the end of %s, %04i-%02i-%02i",
4286 daynames[tm->tm_wday], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday ); 4286 daynames[tm->tm_wday], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday );
4287 } 4287 }
4288 else 4288 else
4289 { 4289 {
4290 snprintf( t, size, "UTC offset parameter: %is, no leap second announced.\n", dtls ); 4290 snprintf( t, size, "UTC offset parameter: %is, no leap second announced.", dtls );
4291 } 4291 }
4292 4292
4293} 4293}
4294 4294
4295#ifdef CLOCK_MEINBERG 4295#ifdef CLOCK_MEINBERG
4296/**=========================================================================== 4296/**===========================================================================
4297 ** Meinberg GPS receiver support 4297 ** Meinberg GPS receiver support
4298 **/ 4298 **/
4299 4299
4300/*------------------------------------------------------------ 4300/*------------------------------------------------------------
4301 * gps16x_message - process messages from Meinberg GPS receiver 4301 * gps16x_message - process messages from Meinberg GPS receiver
4302 */ 4302 */
4303static void 4303static void
4304gps16x_message( 4304gps16x_message(
4305 struct parseunit *parse, 4305 struct parseunit *parse,
4306 parsetime_t *parsetime 4306 parsetime_t *parsetime
4307 ) 4307 )
4308{ 4308{
4309 if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH) 4309 if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
4310 { 4310 {
4311 GPS_MSG_HDR header; 4311 GPS_MSG_HDR header;
4312 unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1; 4312 unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
4313 4313
4314#ifdef DEBUG 4314#ifdef DEBUG
4315 if (debug > 2) 4315 if (debug > 2)
4316 { 4316 {
4317 char msgbuffer[600]; 4317 char msgbuffer[600];
4318 4318
4319 mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1); 4319 mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
4320 printf("PARSE receiver #%d: received message (%d bytes) >%s<\n", 4320 printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
4321 CLK_UNIT(parse->peer), 4321 CLK_UNIT(parse->peer),
4322 parsetime->parse_msglen, 4322 parsetime->parse_msglen,
4323 msgbuffer); 4323 msgbuffer);
4324 } 4324 }
4325#endif 4325#endif
4326 get_mbg_header(&bufp, &header); 4326 get_mbg_header(&bufp, &header);
4327 if (header.hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) && 4327 if (header.hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
4328 (header.len == 0 || 4328 (header.len == 0 ||
4329 (header.len < sizeof(parsetime->parse_msg) && 4329 (header.len < sizeof(parsetime->parse_msg) &&
4330 header.data_csum == mbg_csum(bufp, header.len)))) 4330 header.data_csum == mbg_csum(bufp, header.len))))
4331 { 4331 {
4332 /* 4332 /*
4333 * clean message 4333 * clean message
4334 */ 4334 */
4335 switch (header.cmd) 4335 switch (header.cmd)
4336 { 4336 {
4337 case GPS_SW_REV: 4337 case GPS_SW_REV:
4338 { 4338 {
4339 char buffer[64]; 4339 char buffer[64];
4340 SW_REV gps_sw_rev; 4340 SW_REV gps_sw_rev;
4341 4341
4342 get_mbg_sw_rev(&bufp, &gps_sw_rev); 4342 get_mbg_sw_rev(&bufp, &gps_sw_rev);
4343 snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"", 4343 snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
4344 (gps_sw_rev.code >> 8) & 0xFF, 4344 (gps_sw_rev.code >> 8) & 0xFF,
4345 gps_sw_rev.code & 0xFF, 4345 gps_sw_rev.code & 0xFF,
4346 gps_sw_rev.name[0] ? " " : "", 4346 gps_sw_rev.name[0] ? " " : "",
4347 gps_sw_rev.name); 4347 gps_sw_rev.name);
4348 set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF); 4348 set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4349 } 4349 }
4350 break; 4350 break;
4351 4351
4352 case GPS_BVAR_STAT: 4352 case GPS_BVAR_STAT:
4353 { 4353 {
4354 static struct state 4354 static struct state
4355 { 4355 {
4356 BVAR_STAT flag; /* status flag */ 4356 BVAR_STAT flag; /* status flag */
4357 const char *string; /* bit name */ 4357 const char *string; /* bit name */
4358 } states[] = 4358 } states[] =
4359 { 4359 {
4360 { BVAR_CFGH_INVALID, "Configuration/Health" }, 4360 { BVAR_CFGH_INVALID, "Configuration/Health" },
4361 { BVAR_ALM_NOT_COMPLETE, "Almanachs" }, 4361 { BVAR_ALM_NOT_COMPLETE, "Almanachs" },
4362 { BVAR_UTC_INVALID, "UTC Correction" }, 4362 { BVAR_UTC_INVALID, "UTC Correction" },
4363 { BVAR_IONO_INVALID, "Ionospheric Correction" }, 4363 { BVAR_IONO_INVALID, "Ionospheric Correction" },
4364 { BVAR_RCVR_POS_INVALID, "Receiver Position" }, 4364 { BVAR_RCVR_POS_INVALID, "Receiver Position" },
4365 { 0, "" } 4365 { 0, "" }
4366 }; 4366 };
4367 BVAR_STAT status; 4367 BVAR_STAT status;
4368 struct state *s = states; 4368 struct state *s = states;
4369 char buffer[512]; 4369 char buffer[512];
4370 char *p, *b; 4370 char *p, *b;
4371 4371
4372 status = (BVAR_STAT) get_lsb_short(&bufp); 4372 status = (BVAR_STAT) get_lsb_short(&bufp);
4373 p = b = buffer; 4373 p = b = buffer;
4374 p = ap(buffer, sizeof(buffer), p, 4374 p = ap(buffer, sizeof(buffer), p,
4375 "meinberg_gps_status=\"[0x%04x] ", 4375 "meinberg_gps_status=\"[0x%04x] ",
4376 status); 4376 status);
4377 4377
4378 if (status) 4378 if (status)
4379 { 4379 {
4380 p = ap(buffer, sizeof(buffer), p, "incomplete buffered data: "); 4380 p = ap(buffer, sizeof(buffer), p, "incomplete buffered data: ");
4381 b = p; 4381 b = p;
4382 while (s->flag) 4382 while (s->flag)
4383 { 4383 {
4384 if (status & s->flag) 4384 if (status & s->flag)
4385 { 4385 {
4386 if (p != b) 4386 if (p != b)
4387 { 4387 {
4388 p = ap(buffer, sizeof(buffer), p, ", "); 4388 p = ap(buffer, sizeof(buffer), p, ", ");
4389 } 4389 }
4390 4390
4391 p = ap(buffer, sizeof(buffer), p, "%s", (const char *)s->string); 4391 p = ap(buffer, sizeof(buffer), p, "%s", (const char *)s->string);
4392 } 4392 }
4393 s++; 4393 s++;
4394 } 4394 }
4395 p = ap(buffer, sizeof(buffer), p, "\""); 4395 p = ap(buffer, sizeof(buffer), p, "\"");
4396 } 4396 }
4397 else 4397 else
4398 { 4398 {
4399 p = ap(buffer, sizeof(buffer), p, "<all buffered data complete>\""); 4399 p = ap(buffer, sizeof(buffer), p, "<all buffered data complete>\"");
4400 } 4400 }
4401 4401
4402 set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF); 4402 set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4403 } 4403 }
4404 break; 4404 break;
4405 4405
4406 case GPS_POS_XYZ: 4406 case GPS_POS_XYZ:
4407 { 4407 {
4408 XYZ xyz; 4408 XYZ xyz;
4409 char buffer[256]; 4409 char buffer[256];
4410 4410
4411 get_mbg_xyz(&bufp, xyz); 4411 get_mbg_xyz(&bufp, xyz);
4412 snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"", 4412 snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
4413 mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1), 4413 mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
4414 mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1), 4414 mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
4415 mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1)); 4415 mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
4416 4416
4417 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF); 4417 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4418 } 4418 }
4419 break; 4419 break;
4420 4420
4421 case GPS_POS_LLA: 4421 case GPS_POS_LLA:
4422 { 4422 {
4423 LLA lla; 4423 LLA lla;
4424 char buffer[256]; 4424 char buffer[256];
4425 4425
4426 get_mbg_lla(&bufp, lla); 4426 get_mbg_lla(&bufp, lla);
4427 4427
4428 snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"", 4428 snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
4429 mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4), 4429 mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
4430 mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4), 4430 mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
4431 mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1)); 4431 mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
4432 4432
4433 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF); 4433 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4434 } 4434 }
4435 break; 4435 break;
4436 4436
4437 case GPS_TZDL: 4437 case GPS_TZDL:
4438 break; 4438 break;
4439 4439
4440 case GPS_PORT_PARM: 4440 case GPS_PORT_PARM:
4441 break; 4441 break;
4442 4442
4443 case GPS_SYNTH: 4443 case GPS_SYNTH:
4444 break; 4444 break;
4445 4445
4446 case GPS_ANT_INFO: 4446 case GPS_ANT_INFO:
4447 { 4447 {
4448 ANT_INFO antinfo; 4448 ANT_INFO antinfo;
4449 char buffer[512]; 4449 char buffer[512];
4450 char *p, *q; 4450 char *p, *q;
4451 4451
4452 get_mbg_antinfo(&bufp, &antinfo); 4452 get_mbg_antinfo(&bufp, &antinfo);
4453 p = buffer; 4453 p = buffer;
4454 p = ap(buffer, sizeof(buffer), p, "meinberg_antenna_status=\""); 4454 p = ap(buffer, sizeof(buffer), p, "meinberg_antenna_status=\"");
4455 switch (antinfo.status) 4455 switch (antinfo.status)
4456 { 4456 {
4457 case ANT_INVALID: // No other fields valid since antenna has not yet been disconnected 4457 case ANT_INVALID: // No other fields valid since antenna has not yet been disconnected
4458 p = ap(buffer, sizeof(buffer), 4458 p = ap(buffer, sizeof(buffer),
4459 p, "<OK>"); 4459 p, "<OK>");
4460 break; 4460 break;
4461 4461
4462 case ANT_DISCONN: // Antenna is disconnected, tm_reconn and delta_t not yet set 4462 case ANT_DISCONN: // Antenna is disconnected, tm_reconn and delta_t not yet set
4463 q = ap(buffer, sizeof(buffer), 4463 q = ap(buffer, sizeof(buffer),
4464 p, "DISCONNECTED since "); 4464 p, "DISCONNECTED since ");
4465 NLOG(NLOG_CLOCKSTATUS) 4465 NLOG(NLOG_CLOCKSTATUS)
4466 ERR(ERR_BADSTATUS) 4466 ERR(ERR_BADSTATUS)
4467 msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s", 4467 msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
4468 CLK_UNIT(parse->peer), p); 4468 CLK_UNIT(parse->peer), p);
4469 4469
4470 p = q; 4470 p = q;
4471 mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p), 0); 4471 mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p), 0);
4472 *p = '\0'; 4472 *p = '\0';
4473 break; 4473 break;
4474 4474
4475 case ANT_RECONN: // Antenna had been disconnect, but receiver sync. after reconnect, so all fields valid 4475 case ANT_RECONN: // Antenna had been disconnect, but receiver sync. after reconnect, so all fields valid
4476 p = ap(buffer, sizeof(buffer), 4476 p = ap(buffer, sizeof(buffer),
4477 p, "SYNC AFTER RECONNECT on "); 4477 p, "SYNC AFTER RECONNECT on ");
4478 mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p), 0); 4478 mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p), 0);
4479 p = ap(buffer, sizeof(buffer), 4479 p = ap(buffer, sizeof(buffer),
4480 p, ", clock offset at reconnect %c%ld.%07ld s, disconnect time ", 4480 p, ", clock offset at reconnect %c%ld.%07ld s, disconnect time ",
4481 (antinfo.delta_t < 0) ? '-' : '+', 4481 (antinfo.delta_t < 0) ? '-' : '+',
4482 (long) ABS(antinfo.delta_t) / 10000, 4482 (long) ABS(antinfo.delta_t) / 10000,
4483 (long) ABS(antinfo.delta_t) % 10000); 4483 (long) ABS(antinfo.delta_t) % 10000);
4484 mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p), 0); 4484 mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p), 0);
4485 *p = '\0'; 4485 *p = '\0';
4486 break; 4486 break;
4487 4487
4488 default: 4488 default:
4489 p = ap(buffer, sizeof(buffer), 4489 p = ap(buffer, sizeof(buffer),
4490 p, "bad status 0x%04x", 4490 p, "bad status 0x%04x",
4491 antinfo.status); 4491 antinfo.status);
4492 break; 4492 break;
4493 } 4493 }
4494 4494
4495 p = ap(buffer, sizeof(buffer), p, "\""); 4495 p = ap(buffer, sizeof(buffer), p, "\"");
4496 4496
4497 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF); 4497 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4498 } 4498 }
4499 break; 4499 break;
4500 4500
4501 case GPS_UCAP: 4501 case GPS_UCAP:
4502 break; 4502 break;
4503 4503
4504 case GPS_CFGH: 4504 case GPS_CFGH:
4505 { 4505 {
4506 CFGH cfgh; 4506 CFGH cfgh;
4507 char buffer[512]; 4507 char buffer[512];
4508 char *p; 4508 char *p;
4509 4509
4510 get_mbg_cfgh(&bufp, &cfgh); 4510 get_mbg_cfgh(&bufp, &cfgh);
4511 if (cfgh.valid) 4511 if (cfgh.valid)
4512 { 4512 {
4513 const char *cp; 4513 const char *cp;
4514 uint16_t tmp_val; 4514 uint16_t tmp_val;
4515 int i; 4515 int i;
4516 4516
4517 p = buffer; 4517 p = buffer;
4518 p = ap(buffer, sizeof(buffer), 4518 p = ap(buffer, sizeof(buffer),
4519 p, "gps_tot_51=\""); 4519 p, "gps_tot_51=\"");
4520 mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p)); 4520 mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
4521 p = ap(buffer, sizeof(buffer), 4521 p = ap(buffer, sizeof(buffer),
4522 p, "\""); 4522 p, "\"");
4523 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF); 4523 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF);
4524 4524
4525 p = buffer; 4525 p = buffer;
4526 p = ap(buffer, sizeof(buffer), 4526 p = ap(buffer, sizeof(buffer),
4527 p, "gps_tot_63=\""); 4527 p, "gps_tot_63=\"");
4528 mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p)); 4528 mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
4529 p = ap(buffer, sizeof(buffer), 4529 p = ap(buffer, sizeof(buffer),
4530 p, "\""); 4530 p, "\"");
4531 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF); 4531 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF);
4532 4532
4533 p = buffer; 4533 p = buffer;
4534 p = ap(buffer, sizeof(buffer), 4534 p = ap(buffer, sizeof(buffer),
4535 p, "gps_t0a=\""); 4535 p, "gps_t0a=\"");
4536 mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p)); 4536 mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
4537 p = ap(buffer, sizeof(buffer), 4537 p = ap(buffer, sizeof(buffer),
4538 p, "\""); 4538 p, "\"");
4539 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF); 4539 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF);
4540 4540
4541 for (i = 0; i < N_SVNO_GPS; i++) 4541 for (i = 0; i < N_SVNO_GPS; i++)
4542 { 4542 {
4543 p = buffer; 4543 p = buffer;
4544 p = ap(buffer, sizeof(buffer), p, "sv_info[%d]=\"PRN%d", i, i + N_SVNO_GPS); 4544 p = ap(buffer, sizeof(buffer), p, "sv_info[%d]=\"PRN%d", i, i + N_SVNO_GPS);
4545 4545
4546 tmp_val = cfgh.health[i]; /* a 6 bit SV health code */ 4546 tmp_val = cfgh.health[i]; /* a 6 bit SV health code */
4547 p = ap(buffer, sizeof(buffer), p, "; health=0x%02x (", tmp_val); 4547 p = ap(buffer, sizeof(buffer), p, "; health=0x%02x (", tmp_val);
4548 /* "All Ones" has a special meaning" */ 4548 /* "All Ones" has a special meaning" */
4549 if (tmp_val == 0x3F) /* satellite is unusable or doesn't even exist */ 4549 if (tmp_val == 0x3F) /* satellite is unusable or doesn't even exist */
4550 cp = "SV UNAVAILABLE"; 4550 cp = "SV UNAVAILABLE";
4551 else { 4551 else {
4552 /* The MSB contains a summary of the 3 MSBs of the 8 bit health code, 4552 /* The MSB contains a summary of the 3 MSBs of the 8 bit health code,
4553 * indicating if the data sent by the satellite is OK or not. */ 4553 * indicating if the data sent by the satellite is OK or not. */
4554 p = ap(buffer, sizeof(buffer), p, "DATA %s, ", (tmp_val & 0x20) ? "BAD" : "OK" ); 4554 p = ap(buffer, sizeof(buffer), p, "DATA %s, ", (tmp_val & 0x20) ? "BAD" : "OK" );
4555 4555
4556 /* The 5 LSBs contain the status of the different signals sent by the satellite. */ 4556 /* The 5 LSBs contain the status of the different signals sent by the satellite. */
4557 switch (tmp_val & 0x1F) 4557 switch (tmp_val & 0x1F)
4558 { 4558 {
4559 case 0x00: cp = "SIGNAL OK"; break; 4559 case 0x00: cp = "SIGNAL OK"; break;
4560 /* codes 0x01 through 0x1B indicate that one or more 4560 /* codes 0x01 through 0x1B indicate that one or more
4561 * specific signal components are weak or dead. 4561 * specific signal components are weak or dead.
4562 * We don't decode this here in detail. */ 4562 * We don't decode this here in detail. */
4563 case 0x1C: cp = "SV IS TEMP OUT"; break; 4563 case 0x1C: cp = "SV IS TEMP OUT"; break;
4564 case 0x1D: cp = "SV WILL BE TEMP OUT"; break; 4564 case 0x1D: cp = "SV WILL BE TEMP OUT"; break;
4565 default: cp = "TRANSMISSION PROBLEMS"; break; 4565 default: cp = "TRANSMISSION PROBLEMS"; break;
4566 } 4566 }
4567 } 4567 }
4568 p = ap(buffer, sizeof(buffer), p, "%s)", cp ); 4568 p = ap(buffer, sizeof(buffer), p, "%s)", cp );
4569 4569
4570 tmp_val = cfgh.cfg[i]; /* a 4 bit SV configuration/type code */ 4570 tmp_val = cfgh.cfg[i]; /* a 4 bit SV configuration/type code */
4571 p = ap(buffer, sizeof(buffer), p, "; cfg=0x%02x (", tmp_val); 4571 p = ap(buffer, sizeof(buffer), p, "; cfg=0x%02x (", tmp_val);
4572 switch (tmp_val & 0x7) 4572 switch (tmp_val & 0x7)
4573 { 4573 {
4574 case 0x00: cp = "(reserved)"; break; 4574 case 0x00: cp = "(reserved)"; break;
4575 case 0x01: cp = "BLOCK II/IIA/IIR"; break; 4575 case 0x01: cp = "BLOCK II/IIA/IIR"; break;
4576 case 0x02: cp = "BLOCK IIR-M"; break; 4576 case 0x02: cp = "BLOCK IIR-M"; break;
4577 case 0x03: cp = "BLOCK IIF"; break; 4577 case 0x03: cp = "BLOCK IIF"; break;
4578 case 0x04: cp = "BLOCK III"; break; 4578 case 0x04: cp = "BLOCK III"; break;
4579 default: cp = "unknown SV type"; break; 4579 default: cp = "unknown SV type"; break;
4580 } 4580 }
4581 p = ap(buffer, sizeof(buffer), p, "%s", cp ); 4581 p = ap(buffer, sizeof(buffer), p, "%s", cp );
4582 if (tmp_val & 0x08) /* A-S is on, P-code is encrypted */ 4582 if (tmp_val & 0x08) /* A-S is on, P-code is encrypted */
4583 p = ap( buffer, sizeof(buffer), p, ", A-S on" ); 4583 p = ap( buffer, sizeof(buffer), p, ", A-S on" );
4584 4584
4585 p = ap(buffer, sizeof(buffer), p, ")\""); 4585 p = ap(buffer, sizeof(buffer), p, ")\"");
4586 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF); 4586 set_var(&parse->kv, buffer, sizeof(buffer), RO|COND_DEF);
4587 } 4587 }
4588 } 4588 }
4589 } 4589 }
4590 break; 4590 break;
4591 4591
4592 case GPS_ALM: 4592 case GPS_ALM:
4593 break; 4593 break;
4594 4594
4595 case GPS_EPH: 4595 case GPS_EPH:
4596 break; 4596 break;
4597 4597
4598 case GPS_UTC: 4598 case GPS_UTC:
4599 { 4599 {
4600 UTC utc; 4600 UTC utc;
4601 char buffer[512]; 4601 char buffer[512];
4602 char *p; 4602 char *p;
4603 4603
4604 p = buffer; 4604 p = buffer;
4605 4605
4606 get_mbg_utc(&bufp, &utc); 4606 get_mbg_utc(&bufp, &utc);
4607 4607
4608 if (utc.valid) 4608 if (utc.valid)
4609 { 4609 {
4610 p = ap(buffer, sizeof(buffer), p, "gps_utc_correction=\""); 4610 p = ap(buffer, sizeof(buffer), p, "gps_utc_correction=\"");
4611 mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p)); 4611 mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
4612 p += strlen(p); 4612 p += strlen(p);
4613 p = ap(buffer, sizeof(buffer), p, "\""); 4613 p = ap(buffer, sizeof(buffer), p, "\"");
4614 } 4614 }
4615 else 4615 else
4616 { 4616 {
4617 p = ap(buffer, sizeof(buffer), p, "gps_utc_correction=\"<NO UTC DATA>\""); 4617 p = ap(buffer, sizeof(buffer), p, "gps_utc_correction=\"<NO UTC DATA>\"");
4618 } 4618 }
4619 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF); 4619 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4620 } 4620 }
4621 break; 4621 break;
4622 4622
4623 case GPS_IONO: 4623 case GPS_IONO:
4624 break; 4624 break;
4625 4625
4626 case GPS_ASCII_MSG: 4626 case GPS_ASCII_MSG:
4627 { 4627 {
4628 ASCII_MSG gps_ascii_msg; 4628 ASCII_MSG gps_ascii_msg;
4629 char buffer[128]; 4629 char buffer[128];
4630 4630
4631 get_mbg_ascii_msg(&bufp, &gps_ascii_msg); 4631 get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
4632 4632
4633 if (gps_ascii_msg.valid) 4633 if (gps_ascii_msg.valid)
4634 { 4634 {
4635 char buffer1[128]; 4635 char buffer1[128];
4636 mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0); 4636 mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
4637 4637
4638 snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1); 4638 snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
4639 } 4639 }
4640 else 4640 else
4641 snprintf(buffer, sizeof(buffer), "gps_message=<NONE>"); 4641 snprintf(buffer, sizeof(buffer), "gps_message=<NONE>");
4642 4642
4643 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF); 4643 set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4644 } 4644 }
4645 4645
4646 break; 4646 break;
4647 4647
4648 default: 4648 default:
4649 break; 4649 break;
4650 } 4650 }
4651 } 4651 }
4652 else 4652 else
4653 { 4653 {
4654 msyslog(LOG_DEBUG, "PARSE receiver #%d: gps16x_message: message checksum error: hdr_csum = 0x%x (expected 0x%x), " 4654 msyslog(LOG_DEBUG, "PARSE receiver #%d: gps16x_message: message checksum error: hdr_csum = 0x%x (expected 0x%x), "
4655 "data_len = %d, data_csum = 0x%x (expected 0x%x)", 4655 "data_len = %d, data_csum = 0x%x (expected 0x%x)",
4656 CLK_UNIT(parse->peer), 4656 CLK_UNIT(parse->peer),
4657 header.hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6), 4657 header.hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
4658 header.len, 4658 header.len,
4659 header.data_csum, mbg_csum(bufp, (unsigned)((header.len < sizeof(parsetime->parse_msg)) ? header.len : 0))); 4659 header.data_csum, mbg_csum(bufp, (unsigned)((header.len < sizeof(parsetime->parse_msg)) ? header.len : 0)));
4660 } 4660 }
4661 } 4661 }
4662 4662
4663 return; 4663 return;
4664} 4664}
4665 4665
4666/*------------------------------------------------------------ 4666/*------------------------------------------------------------
4667 * gps16x_poll - query the reciver peridically 4667 * gps16x_poll - query the reciver peridically
4668 */ 4668 */
4669static void 4669static void
4670gps16x_poll( 4670gps16x_poll(
4671 struct peer *peer 4671 struct peer *peer
4672 ) 4672 )
4673{ 4673{
4674 struct parseunit *parse = peer->procptr->unitptr; 4674 struct parseunit *parse = peer->procptr->unitptr;
4675 4675
4676 static GPS_MSG_HDR sequence[] = 4676 static GPS_MSG_HDR sequence[] =
4677 { 4677 {
4678 { GPS_SW_REV, 0, 0, 0 }, 4678 { GPS_SW_REV, 0, 0, 0 },
4679 { GPS_BVAR_STAT, 0, 0, 0 }, 4679 { GPS_BVAR_STAT, 0, 0, 0 },
4680 { GPS_UTC, 0, 0, 0 }, 4680 { GPS_UTC, 0, 0, 0 },
4681 { GPS_ASCII_MSG, 0, 0, 0 }, 4681 { GPS_ASCII_MSG, 0, 0, 0 },
4682 { GPS_ANT_INFO, 0, 0, 0 }, 4682 { GPS_ANT_INFO, 0, 0, 0 },
4683 { GPS_CFGH, 0, 0, 0 }, 4683 { GPS_CFGH, 0, 0, 0 },
4684 { GPS_POS_XYZ, 0, 0, 0 }, 4684 { GPS_POS_XYZ, 0, 0, 0 },
4685 { GPS_POS_LLA, 0, 0, 0 }, 4685 { GPS_POS_LLA, 0, 0, 0 },
4686 { (unsigned short)~0, 0, 0, 0 } 4686 { (unsigned short)~0, 0, 0, 0 }
4687 }; 4687 };
4688 4688
4689 int rtc; 4689 int rtc;
4690 unsigned char cmd_buffer[64]; 4690 unsigned char cmd_buffer[64];
4691 unsigned char *outp = cmd_buffer; 4691 unsigned char *outp = cmd_buffer;
4692 GPS_MSG_HDR *header; 4692 GPS_MSG_HDR *header;
4693 4693
4694 if (((poll_info_t *)parse->parse_type->cl_data)->rate) 4694 if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4695 { 4695 {
4696 parse->peer->procptr->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate; 4696 parse->peer->procptr->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
4697 } 4697 }
4698 4698
4699 if (sequence[parse->localstate].cmd == (unsigned short)~0) 4699 if (sequence[parse->localstate].cmd == (unsigned short)~0)
4700 parse->localstate = 0; 4700 parse->localstate = 0;
4701 4701
4702 header = sequence + parse->localstate++; 4702 header = sequence + parse->localstate++;
4703 4703
4704 *outp++ = SOH; /* start command */ 4704 *outp++ = SOH; /* start command */
4705 4705
4706 put_mbg_header(&outp, header); 4706 put_mbg_header(&outp, header);
4707 outp = cmd_buffer + 1; 4707 outp = cmd_buffer + 1;
4708 4708
4709 header->hdr_csum = (short)mbg_csum(outp, 6); 4709 header->hdr_csum = (short)mbg_csum(outp, 6);
4710 put_mbg_header(&outp, header); 4710 put_mbg_header(&outp, header);
4711 4711
4712#ifdef DEBUG 4712#ifdef DEBUG
4713 if (debug > 2) 4713 if (debug > 2)
4714 { 4714 {
4715 char buffer[128]; 4715 char buffer[128];
4716 4716
4717 mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1); 4717 mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
4718 printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n", 4718 printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
4719 CLK_UNIT(parse->peer), 4719 CLK_UNIT(parse->peer),
4720 parse->localstate - 1, 4720 parse->localstate - 1,
4721 (int)(outp - cmd_buffer), 4721 (int)(outp - cmd_buffer),
4722 buffer); 4722 buffer);
4723 } 4723 }
4724#endif 4724#endif
4725 4725
4726 rtc = (int) write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer)); 4726 rtc = (int) write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
4727 4727
4728 if (rtc < 0) 4728 if (rtc < 0)
4729 { 4729 {
4730 ERR(ERR_BADIO) 4730 ERR(ERR_BADIO)
4731 msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer)); 4731 msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4732 } 4732 }
4733 else 4733 else
4734 if (rtc != outp - cmd_buffer) 4734 if (rtc != outp - cmd_buffer)
4735 { 4735 {
4736 ERR(ERR_BADIO) 4736 ERR(ERR_BADIO)
4737 msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, (int)(outp - cmd_buffer)); 4737 msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, (int)(outp - cmd_buffer));
4738 } 4738 }
4739 4739
4740 clear_err(parse, ERR_BADIO); 4740 clear_err(parse, ERR_BADIO);
4741 return; 4741 return;
4742} 4742}
4743 4743
4744/*-------------------------------------------------- 4744/*--------------------------------------------------
4745 * init routine - setup timer 4745 * init routine - setup timer
4746 */ 4746 */
4747static int 4747static int
4748gps16x_poll_init( 4748gps16x_poll_init(
4749 struct parseunit *parse 4749 struct parseunit *parse
4750 ) 4750 )
4751{ 4751{
4752 if (((poll_info_t *)parse->parse_type->cl_data)->rate) 4752 if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4753 { 4753 {
4754 parse->peer->procptr->action = gps16x_poll; 4754 parse->peer->procptr->action = gps16x_poll;
4755 gps16x_poll(parse->peer); 4755 gps16x_poll(parse->peer);
4756 } 4756 }
4757 4757
4758 return 0; 4758 return 0;
4759} 4759}
4760 4760
4761#else 4761#else
4762static void 4762static void
4763gps16x_message( 4763gps16x_message(
4764 struct parseunit *parse, 4764 struct parseunit *parse,
4765 parsetime_t *parsetime 4765 parsetime_t *parsetime
4766 ) 4766 )
4767{} 4767{}
4768static int 4768static int
4769gps16x_poll_init( 4769gps16x_poll_init(
4770 struct parseunit *parse 4770 struct parseunit *parse
4771 ) 4771 )
4772{ 4772{
4773 return 1; 4773 return 1;
4774} 4774}
4775#endif /* CLOCK_MEINBERG */ 4775#endif /* CLOCK_MEINBERG */
4776 4776
4777/**=========================================================================== 4777/**===========================================================================
4778 ** clock polling support 4778 ** clock polling support
4779 **/ 4779 **/
4780 4780
4781/*-------------------------------------------------- 4781/*--------------------------------------------------
4782 * direct poll routine 4782 * direct poll routine
4783 */ 4783 */
4784static void 4784static void
4785poll_dpoll( 4785poll_dpoll(
4786 struct parseunit *parse 4786 struct parseunit *parse
4787 ) 4787 )
4788{ 4788{
4789 long rtc; 4789 long rtc;
4790 const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string; 4790 const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
4791 long ct = ((poll_info_t *)parse->parse_type->cl_data)->count; 4791 long ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
4792 4792
4793 rtc = write(parse->generic->io.fd, ps, ct); 4793 rtc = write(parse->generic->io.fd, ps, ct);
4794 if (rtc < 0) 4794 if (rtc < 0)
4795 { 4795 {
4796 ERR(ERR_BADIO) 4796 ERR(ERR_BADIO)
4797 msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer)); 4797 msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4798 } 4798 }
4799 else 4799 else
4800 if (rtc != ct) 4800 if (rtc != ct)
4801 { 4801 {
4802 ERR(ERR_BADIO) 4802 ERR(ERR_BADIO)
4803 msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%ld of %ld bytes sent)", CLK_UNIT(parse->peer), rtc, ct); 4803 msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%ld of %ld bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
4804 } 4804 }
4805 clear_err(parse, ERR_BADIO); 4805 clear_err(parse, ERR_BADIO);
4806} 4806}
4807 4807
4808/*-------------------------------------------------- 4808/*--------------------------------------------------
4809 * periodic poll routine 4809 * periodic poll routine
4810 */ 4810 */
4811static void 4811static void
4812poll_poll( 4812poll_poll(
4813 struct peer *peer 4813 struct peer *peer
4814 ) 4814 )
4815{ 4815{
4816 struct parseunit *parse = peer->procptr->unitptr; 4816 struct parseunit *parse = peer->procptr->unitptr;
4817 4817
4818 if (parse->parse_type->cl_poll) 4818 if (parse->parse_type->cl_poll)
4819 parse->parse_type->cl_poll(parse); 4819 parse->parse_type->cl_poll(parse);
4820 4820
4821 if (((poll_info_t *)parse->parse_type->cl_data)->rate) 4821 if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4822 { 4822 {
4823 parse->peer->procptr->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate; 4823 parse->peer->procptr->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
4824 } 4824 }
4825} 4825}
4826 4826
4827/*-------------------------------------------------- 4827/*--------------------------------------------------
4828 * init routine - setup timer 4828 * init routine - setup timer
4829 */ 4829 */
4830static int 4830static int
4831poll_init( 4831poll_init(
4832 struct parseunit *parse 4832 struct parseunit *parse
4833 ) 4833 )
4834{ 4834{
4835 if (((poll_info_t *)parse->parse_type->cl_data)->rate) 4835 if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4836 { 4836 {
4837 parse->peer->procptr->action = poll_poll; 4837 parse->peer->procptr->action = poll_poll;
4838 poll_poll(parse->peer); 4838 poll_poll(parse->peer);
4839 } 4839 }
4840 4840
4841 return 0; 4841 return 0;
4842} 4842}
4843 4843
4844/**=========================================================================== 4844/**===========================================================================
4845 ** Trimble support 4845 ** Trimble support
4846 **/ 4846 **/
4847 4847
4848/*------------------------------------------------------------- 4848/*-------------------------------------------------------------
4849 * trimble TAIP init routine - setup EOL and then do poll_init. 4849 * trimble TAIP init routine - setup EOL and then do poll_init.
4850 */ 4850 */
4851static int 4851static int
4852trimbletaip_init( 4852trimbletaip_init(
4853 struct parseunit *parse 4853 struct parseunit *parse
4854 ) 4854 )
4855{ 4855{
4856#ifdef HAVE_TERMIOS 4856#ifdef HAVE_TERMIOS
4857 struct termios tio; 4857 struct termios tio;
4858#endif 4858#endif
4859#ifdef HAVE_SYSV_TTYS 4859#ifdef HAVE_SYSV_TTYS
4860 struct termio tio; 4860 struct termio tio;
4861#endif 4861#endif
4862 /* 4862 /*
4863 * configure terminal line for trimble receiver 4863 * configure terminal line for trimble receiver
4864 */ 4864 */
4865 if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1) 4865 if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
4866 { 4866 {
4867 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer)); 4867 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
4868 return 0; 4868 return 0;
4869 } 4869 }
4870 else 4870 else
4871 { 4871 {
4872 tio.c_cc[VEOL] = TRIMBLETAIP_EOL; 4872 tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
4873 4873
4874 if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1) 4874 if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
4875 { 4875 {
4876 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer)); 4876 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
4877 return 0; 4877 return 0;
4878 } 4878 }
4879 } 4879 }
4880 return poll_init(parse); 4880 return poll_init(parse);
4881} 4881}
4882 4882
4883/*-------------------------------------------------- 4883/*--------------------------------------------------
4884 * trimble TAIP event routine - reset receiver upon data format trouble 4884 * trimble TAIP event routine - reset receiver upon data format trouble
4885 */ 4885 */
4886static const char *taipinit[] = { 4886static const char *taipinit[] = {
4887 ">FPV00000000<", 4887 ">FPV00000000<",
4888 ">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<", 4888 ">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
4889 ">FTM00020001<", 4889 ">FTM00020001<",
4890 (char *)0 4890 (char *)0
4891}; 4891};
4892 4892
4893static void 4893static void
4894trimbletaip_event( 4894trimbletaip_event(
4895 struct parseunit *parse, 4895 struct parseunit *parse,
4896 int event 4896 int event
4897 ) 4897 )
4898{ 4898{
4899 switch (event) 4899 switch (event)
4900 { 4900 {
4901 case CEVNT_BADREPLY: /* reset on garbled input */ 4901 case CEVNT_BADREPLY: /* reset on garbled input */
4902 case CEVNT_TIMEOUT: /* reset on no input */ 4902 case CEVNT_TIMEOUT: /* reset on no input */
4903 { 4903 {
4904 const char **iv; 4904 const char **iv;
4905 4905
4906 iv = taipinit; 4906 iv = taipinit;
4907 while (*iv) 4907 while (*iv)
4908 { 4908 {
4909 int rtc = (int) write(parse->generic->io.fd, *iv, strlen(*iv)); 4909 int rtc = (int) write(parse->generic->io.fd, *iv, strlen(*iv));
4910 if (rtc < 0) 4910 if (rtc < 0)
4911 { 4911 {
4912 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer)); 4912 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4913 return; 4913 return;
4914 } 4914 }
4915 else 4915 else
4916 { 4916 {
4917 if (rtc != (int)strlen(*iv)) 4917 if (rtc != (int)strlen(*iv))
4918 { 4918 {
4919 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)", 4919 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
4920 CLK_UNIT(parse->peer), rtc, (int)strlen(*iv)); 4920 CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
4921 return; 4921 return;
4922 } 4922 }
4923 } 4923 }
4924 iv++; 4924 iv++;
4925 } 4925 }
4926 4926
4927 NLOG(NLOG_CLOCKINFO) 4927 NLOG(NLOG_CLOCKINFO)
4928 ERR(ERR_BADIO) 4928 ERR(ERR_BADIO)
4929 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED", 4929 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
4930 CLK_UNIT(parse->peer)); 4930 CLK_UNIT(parse->peer));
4931 } 4931 }
4932 break; 4932 break;
4933 4933
4934 default: /* ignore */ 4934 default: /* ignore */
4935 break; 4935 break;
4936 } 4936 }
4937} 4937}
4938 4938
4939/* 4939/*
4940 * This driver supports the Trimble SVee Six Plus GPS receiver module. 4940 * This driver supports the Trimble SVee Six Plus GPS receiver module.
4941 * It should support other Trimble receivers which use the Trimble Standard 4941 * It should support other Trimble receivers which use the Trimble Standard
4942 * Interface Protocol (see below). 4942 * Interface Protocol (see below).
4943 * 4943 *
4944 * The module has a serial I/O port for command/data and a 1 pulse-per-second 4944 * The module has a serial I/O port for command/data and a 1 pulse-per-second
4945 * output, about 1 microsecond wide. The leading edge of the pulse is 4945 * output, about 1 microsecond wide. The leading edge of the pulse is
4946 * coincident with the change of the GPS second. This is the same as 4946 * coincident with the change of the GPS second. This is the same as
4947 * the change of the UTC second +/- ~1 microsecond. Some other clocks 4947 * the change of the UTC second +/- ~1 microsecond. Some other clocks
4948 * specifically use a feature in the data message as a timing reference, but 4948 * specifically use a feature in the data message as a timing reference, but
4949 * the SVee Six Plus does not do this. In fact there is considerable jitter 4949 * the SVee Six Plus does not do this. In fact there is considerable jitter
4950 * on the timing of the messages, so this driver only supports the use 4950 * on the timing of the messages, so this driver only supports the use
4951 * of the PPS pulse for accurate timing. Where it is determined that 4951 * of the PPS pulse for accurate timing. Where it is determined that
4952 * the offset is way off, when first starting up ntpd for example, 4952 * the offset is way off, when first starting up ntpd for example,
4953 * the timing of the data stream is used until the offset becomes low enough 4953 * the timing of the data stream is used until the offset becomes low enough
4954 * (|offset| < CLOCK_MAX), at which point the pps offset is used. 4954 * (|offset| < CLOCK_MAX), at which point the pps offset is used.
4955 * 4955 *
4956 * It can use either option for receiving PPS information - the 'ppsclock' 4956 * It can use either option for receiving PPS information - the 'ppsclock'
4957 * stream pushed onto the serial data interface to timestamp the Carrier 4957 * stream pushed onto the serial data interface to timestamp the Carrier
4958 * Detect interrupts, where the 1PPS connects to the CD line. This only 4958 * Detect interrupts, where the 1PPS connects to the CD line. This only
4959 * works on SunOS 4.1.x currently. To select this, define PPSPPS in 4959 * works on SunOS 4.1.x currently. To select this, define PPSPPS in
4960 * Config.local. The other option is to use a pulse-stretcher/level-converter 4960 * Config.local. The other option is to use a pulse-stretcher/level-converter
4961 * to convert the PPS pulse into a RS232 start pulse & feed this into another 4961 * to convert the PPS pulse into a RS232 start pulse & feed this into another
4962 * tty port. To use this option, define PPSCLK in Config.local. The pps input, 4962 * tty port. To use this option, define PPSCLK in Config.local. The pps input,
4963 * by whichever method, is handled in ntp_loopfilter.c 4963 * by whichever method, is handled in ntp_loopfilter.c
4964 * 4964 *
4965 * The receiver uses a serial message protocol called Trimble Standard 4965 * The receiver uses a serial message protocol called Trimble Standard
4966 * Interface Protocol (it can support others but this driver only supports 4966 * Interface Protocol (it can support others but this driver only supports
4967 * TSIP). Messages in this protocol have the following form: 4967 * TSIP). Messages in this protocol have the following form:
4968 * 4968 *
4969 * <DLE><id> ... <data> ... <DLE><ETX> 4969 * <DLE><id> ... <data> ... <DLE><ETX>
4970 * 4970 *
4971 * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled 4971 * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
4972 * on transmission and compressed back to one on reception. Otherwise 4972 * on transmission and compressed back to one on reception. Otherwise
4973 * the values of data bytes can be anything. The serial interface is RS-422 4973 * the values of data bytes can be anything. The serial interface is RS-422
4974 * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits 4974 * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
4975 * in total!), and 1 stop bit. The protocol supports byte, integer, single, 4975 * in total!), and 1 stop bit. The protocol supports byte, integer, single,
4976 * and double datatypes. Integers are two bytes, sent most significant first. 4976 * and double datatypes. Integers are two bytes, sent most significant first.
4977 * Singles are IEEE754 single precision floating point numbers (4 byte) sent 4977 * Singles are IEEE754 single precision floating point numbers (4 byte) sent
4978 * sign & exponent first. Doubles are IEEE754 double precision floating point 4978 * sign & exponent first. Doubles are IEEE754 double precision floating point
4979 * numbers (8 byte) sent sign & exponent first. 4979 * numbers (8 byte) sent sign & exponent first.
4980 * The receiver supports a large set of messages, only a small subset of 4980 * The receiver supports a large set of messages, only a small subset of
4981 * which are used here. From driver to receiver the following are used: 4981 * which are used here. From driver to receiver the following are used:
4982 * 4982 *
4983 * ID Description 4983 * ID Description
4984 * 4984 *
4985 * 21 Request current time 4985 * 21 Request current time
4986 * 22 Mode Select 4986 * 22 Mode Select
4987 * 2C Set/Request operating parameters 4987 * 2C Set/Request operating parameters
4988 * 2F Request UTC info 4988 * 2F Request UTC info
4989 * 35 Set/Request I/O options 4989 * 35 Set/Request I/O options
4990 4990
4991 * From receiver to driver the following are recognised: 4991 * From receiver to driver the following are recognised:
4992 * 4992 *
4993 * ID Description 4993 * ID Description
4994 * 4994 *
4995 * 41 GPS Time 4995 * 41 GPS Time
4996 * 44 Satellite selection, PDOP, mode 4996 * 44 Satellite selection, PDOP, mode
4997 * 46 Receiver health 4997 * 46 Receiver health
4998 * 4B Machine code/status 4998 * 4B Machine code/status
4999 * 4C Report operating parameters (debug only) 4999 * 4C Report operating parameters (debug only)
5000 * 4F UTC correction data (used to get leap second warnings) 5000 * 4F UTC correction data (used to get leap second warnings)
5001 * 55 I/O options (debug only) 5001 * 55 I/O options (debug only)
5002 * 5002 *
5003 * All others are accepted but ignored. 5003 * All others are accepted but ignored.
5004 * 5004 *
5005 */ 5005 */
5006 5006
5007#define PI 3.1415926535898 /* lots of sig figs */ 5007#define PI 3.1415926535898 /* lots of sig figs */
5008#define D2R PI/180.0 5008#define D2R PI/180.0
5009 5009
5010/*------------------------------------------------------------------- 5010/*-------------------------------------------------------------------
5011 * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command 5011 * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
5012 * interface to the receiver. 5012 * interface to the receiver.
5013 * 5013 *
5014 * CAVEAT: the sendflt, sendint routines are byte order dependend and 5014 * CAVEAT: the sendflt, sendint routines are byte order dependend and
5015 * float implementation dependend - these must be converted to portable 5015 * float implementation dependend - these must be converted to portable
5016 * versions ! 5016 * versions !
5017 * 5017 *
5018 * CURRENT LIMITATION: float implementation. This runs only on systems 5018 * CURRENT LIMITATION: float implementation. This runs only on systems
5019 * with IEEE754 floats as native floats 5019 * with IEEE754 floats as native floats
5020 */ 5020 */
5021 5021
5022typedef struct trimble 5022typedef struct trimble
5023{ 5023{
5024 u_long last_msg; /* last message received */ 5024 u_long last_msg; /* last message received */
5025 u_long last_reset; /* last time a reset was issued */ 5025 u_long last_reset; /* last time a reset was issued */
5026 u_char qtracking; /* query tracking status */ 5026 u_char qtracking; /* query tracking status */
5027 u_long ctrack; /* current tracking set */ 5027 u_long ctrack; /* current tracking set */
5028 u_long ltrack; /* last tracking set */ 5028 u_long ltrack; /* last tracking set */
5029} trimble_t; 5029} trimble_t;
5030 5030
5031union uval { 5031union uval {
5032 u_char bd[8]; 5032 u_char bd[8];
5033 int iv; 5033 int iv;
5034 float fv; 5034 float fv;
5035 double dv; 5035 double dv;
5036}; 5036};
5037 5037
5038struct txbuf 5038struct txbuf
5039{ 5039{
5040 short idx; /* index to first unused byte */ 5040 short idx; /* index to first unused byte */
5041 u_char *txt; /* pointer to actual data buffer */ 5041 u_char *txt; /* pointer to actual data buffer */
5042}; 5042};
5043 5043
5044void sendcmd (struct txbuf *buf, int c); 5044void sendcmd (struct txbuf *buf, int c);
5045void sendbyte (struct txbuf *buf, int b); 5045void sendbyte (struct txbuf *buf, int b);
5046void sendetx (struct txbuf *buf, struct parseunit *parse); 5046void sendetx (struct txbuf *buf, struct parseunit *parse);
5047void sendint (struct txbuf *buf, int a); 5047void sendint (struct txbuf *buf, int a);
5048void sendflt (struct txbuf *buf, double a); 5048void sendflt (struct txbuf *buf, double a);
5049 5049
5050void 5050void
5051sendcmd( 5051sendcmd(
5052 struct txbuf *buf, 5052 struct txbuf *buf,
5053 int c 5053 int c
5054 ) 5054 )
5055{ 5055{
5056 buf->txt[0] = DLE; 5056 buf->txt[0] = DLE;
5057 buf->txt[1] = (u_char)c; 5057 buf->txt[1] = (u_char)c;
5058 buf->idx = 2; 5058 buf->idx = 2;
5059} 5059}
5060 5060
5061void sendcmd (struct txbuf *buf, int c); 5061void sendcmd (struct txbuf *buf, int c);
5062void sendbyte (struct txbuf *buf, int b); 5062void sendbyte (struct txbuf *buf, int b);
5063void sendetx (struct txbuf *buf, struct parseunit *parse); 5063void sendetx (struct txbuf *buf, struct parseunit *parse);
5064void sendint (struct txbuf *buf, int a); 5064void sendint (struct txbuf *buf, int a);
5065void sendflt (struct txbuf *buf, double a); 5065void sendflt (struct txbuf *buf, double a);
5066 5066
5067void 5067void
5068sendbyte( 5068sendbyte(
5069 struct txbuf *buf, 5069 struct txbuf *buf,
5070 int b 5070 int b
5071 ) 5071 )
5072{ 5072{
5073 if (b == DLE) 5073 if (b == DLE)
5074 buf->txt[buf->idx++] = DLE; 5074 buf->txt[buf->idx++] = DLE;
5075 buf->txt[buf->idx++] = (u_char)b; 5075 buf->txt[buf->idx++] = (u_char)b;
5076} 5076}
5077 5077
5078void 5078void
5079sendetx( 5079sendetx(
5080 struct txbuf *buf, 5080 struct txbuf *buf,
5081 struct parseunit *parse 5081 struct parseunit *parse
5082 ) 5082 )
5083{ 5083{
5084 buf->txt[buf->idx++] = DLE; 5084 buf->txt[buf->idx++] = DLE;
5085 buf->txt[buf->idx++] = ETX; 5085 buf->txt[buf->idx++] = ETX;
5086 5086
5087 if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx) 5087 if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
5088 { 5088 {
5089 ERR(ERR_BADIO) 5089 ERR(ERR_BADIO)
5090 msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer)); 5090 msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
5091 } 5091 }
5092 else 5092 else
5093 { 5093 {
5094#ifdef DEBUG 5094#ifdef DEBUG
5095 if (debug > 2) 5095 if (debug > 2)
5096 { 5096 {
5097 char buffer[256]; 5097 char buffer[256];
5098 5098
5099 mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1); 5099 mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
5100 printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n", 5100 printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
5101 CLK_UNIT(parse->peer), 5101 CLK_UNIT(parse->peer),
5102 buf->idx, buffer); 5102 buf->idx, buffer);
5103 } 5103 }
5104#endif 5104#endif
5105 clear_err(parse, ERR_BADIO); 5105 clear_err(parse, ERR_BADIO);
5106 } 5106 }
5107} 5107}
5108 5108
5109void 5109void
5110sendint( 5110sendint(
5111 struct txbuf *buf, 5111 struct txbuf *buf,
5112 int a 5112 int a
5113 ) 5113 )
5114{ 5114{
5115 /* send 16bit int, msbyte first */ 5115 /* send 16bit int, msbyte first */
5116 sendbyte(buf, (u_char)((a>>8) & 0xff)); 5116 sendbyte(buf, (u_char)((a>>8) & 0xff));
5117 sendbyte(buf, (u_char)(a & 0xff)); 5117 sendbyte(buf, (u_char)(a & 0xff));
5118} 5118}
5119 5119
5120void 5120void
5121sendflt( 5121sendflt(
5122 struct txbuf *buf, 5122 struct txbuf *buf,
5123 double a 5123 double a
5124 ) 5124 )
5125{ 5125{
5126 int i; 5126 int i;
5127 union uval uval; 5127 union uval uval;
5128 5128
5129 uval.fv = (float) a; 5129 uval.fv = (float) a;
5130#ifdef WORDS_BIGENDIAN 5130#ifdef WORDS_BIGENDIAN
5131 for (i=0; i<=3; i++) 5131 for (i=0; i<=3; i++)
5132#else 5132#else
5133 for (i=3; i>=0; i--) 5133 for (i=3; i>=0; i--)
5134#endif 5134#endif
5135 sendbyte(buf, uval.bd[i]); 5135 sendbyte(buf, uval.bd[i]);
5136} 5136}
5137 5137
5138#define TRIM_POS_OPT 0x13 /* output position with high precision */ 5138#define TRIM_POS_OPT 0x13 /* output position with high precision */
5139#define TRIM_TIME_OPT 0x03 /* use UTC time stamps, on second */ 5139#define TRIM_TIME_OPT 0x03 /* use UTC time stamps, on second */
5140 5140
5141/*-------------------------------------------------- 5141/*--------------------------------------------------
5142 * trimble TSIP setup routine 5142 * trimble TSIP setup routine
5143 */ 5143 */
5144static int 5144static int
5145trimbletsip_setup( 5145trimbletsip_setup(
5146 struct parseunit *parse, 5146 struct parseunit *parse,
5147 const char *reason 5147 const char *reason
5148 ) 5148 )
5149{ 5149{
5150 u_char buffer[256]; 5150 u_char buffer[256];
5151 struct txbuf buf; 5151 struct txbuf buf;
5152 trimble_t *t = parse->localdata; 5152 trimble_t *t = parse->localdata;
5153 5153
5154 if (t && t->last_reset && 5154 if (t && t->last_reset &&
5155 ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) { 5155 ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
5156 return 1; /* not yet */ 5156 return 1; /* not yet */
5157 } 5157 }
5158 5158
5159 if (t) 5159 if (t)
5160 t->last_reset = current_time; 5160 t->last_reset = current_time;
5161 5161
5162 buf.txt = buffer; 5162 buf.txt = buffer;
5163 5163
5164 sendcmd(&buf, CMD_CVERSION); /* request software versions */ 5164 sendcmd(&buf, CMD_CVERSION); /* request software versions */
5165 sendetx(&buf, parse); 5165 sendetx(&buf, parse);
5166 5166
5167 sendcmd(&buf, CMD_COPERPARAM); /* set operating parameters */ 5167 sendcmd(&buf, CMD_COPERPARAM); /* set operating parameters */
5168 sendbyte(&buf, 4); /* static */ 5168 sendbyte(&buf, 4); /* static */
5169 sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */ 5169 sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */
5170 sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */ 5170 sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */
5171 sendflt(&buf, 12.0); /* PDOP mask = 12 */ 5171 sendflt(&buf, 12.0); /* PDOP mask = 12 */
5172 sendflt(&buf, 8.0); /* PDOP switch level = 8 */ 5172 sendflt(&buf, 8.0); /* PDOP switch level = 8 */
5173 sendetx(&buf, parse); 5173 sendetx(&buf, parse);
5174 5174
5175 sendcmd(&buf, CMD_CMODESEL); /* fix mode select */ 5175 sendcmd(&buf, CMD_CMODESEL); /* fix mode select */
5176 sendbyte(&buf, 1); /* time transfer mode */ 5176 sendbyte(&buf, 1); /* time transfer mode */
5177 sendetx(&buf, parse); 5177 sendetx(&buf, parse);
5178 5178
5179 sendcmd(&buf, CMD_CMESSAGE); /* request system message */ 5179 sendcmd(&buf, CMD_CMESSAGE); /* request system message */
5180 sendetx(&buf, parse); 5180 sendetx(&buf, parse);
5181 5181
5182 sendcmd(&buf, CMD_CSUPER); /* superpacket fix */ 5182 sendcmd(&buf, CMD_CSUPER); /* superpacket fix */
5183 sendbyte(&buf, 0x2); /* binary mode */ 5183 sendbyte(&buf, 0x2); /* binary mode */
5184 sendetx(&buf, parse); 5184 sendetx(&buf, parse);
5185 5185
5186 sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */ 5186 sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */
5187 sendbyte(&buf, TRIM_POS_OPT); /* position output */ 5187 sendbyte(&buf, TRIM_POS_OPT); /* position output */
5188 sendbyte(&buf, 0x00); /* no velocity output */ 5188 sendbyte(&buf, 0x00); /* no velocity output */
5189 sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */ 5189 sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */
5190 sendbyte(&buf, 0x00); /* no raw measurements */ 5190 sendbyte(&buf, 0x00); /* no raw measurements */
5191 sendetx(&buf, parse); 5191 sendetx(&buf, parse);
5192 5192
5193 sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */ 5193 sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */
5194 sendetx(&buf, parse); 5194 sendetx(&buf, parse);
5195 5195
5196 NLOG(NLOG_CLOCKINFO) 5196 NLOG(NLOG_CLOCKINFO)
5197 ERR(ERR_BADIO) 5197 ERR(ERR_BADIO)
5198 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason); 5198 msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
5199 5199
5200 return 0; 5200 return 0;
5201} 5201}
5202 5202
5203/*-------------------------------------------------- 5203/*--------------------------------------------------
5204 * TRIMBLE TSIP check routine 5204 * TRIMBLE TSIP check routine
5205 */ 5205 */
5206static void 5206static void
5207trimble_check( 5207trimble_check(
5208 struct peer *peer 5208 struct peer *peer
5209 ) 5209 )
5210{ 5210{
5211 struct parseunit *parse = peer->procptr->unitptr; 5211 struct parseunit *parse = peer->procptr->unitptr;
5212 trimble_t *t = parse->localdata; 5212 trimble_t *t = parse->localdata;
5213 u_char buffer[256]; 5213 u_char buffer[256];
5214 struct txbuf buf; 5214 struct txbuf buf;
5215 buf.txt = buffer; 5215 buf.txt = buffer;
5216 5216
5217 if (t) 5217 if (t)
5218 { 5218 {
5219 if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME) 5219 if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
5220 (void)trimbletsip_setup(parse, "message timeout"); 5220 (void)trimbletsip_setup(parse, "message timeout");
5221 } 5221 }
5222 5222
5223 poll_poll(parse->peer); /* emit query string and re-arm timer */ 5223 poll_poll(parse->peer); /* emit query string and re-arm timer */
5224 5224
5225 if (t && t->qtracking) 5225 if (t && t->qtracking)
5226 { 5226 {
5227 u_long oldsats = t->ltrack & ~t->ctrack; 5227 u_long oldsats = t->ltrack & ~t->ctrack;
5228 5228
5229 t->qtracking = 0; 5229 t->qtracking = 0;
5230 t->ltrack = t->ctrack; 5230 t->ltrack = t->ctrack;
5231 5231
5232 if (oldsats) 5232 if (oldsats)
5233 { 5233 {
5234 int i; 5234 int i;
5235 5235
5236 for (i = 0; oldsats; i++) { 5236 for (i = 0; oldsats; i++) {
5237 if (oldsats & (1 << i)) 5237 if (oldsats & (1 << i))
5238 { 5238 {
5239 sendcmd(&buf, CMD_CSTATTRACK); 5239 sendcmd(&buf, CMD_CSTATTRACK);
5240 sendbyte(&buf, i+1); /* old sat */ 5240 sendbyte(&buf, i+1); /* old sat */
5241 sendetx(&buf, parse); 5241 sendetx(&buf, parse);
5242 } 5242 }
5243 oldsats &= ~(1 << i); 5243 oldsats &= ~(1 << i);
5244 } 5244 }
5245 } 5245 }
5246 5246
5247 sendcmd(&buf, CMD_CSTATTRACK); 5247 sendcmd(&buf, CMD_CSTATTRACK);
5248 sendbyte(&buf, 0x00); /* current tracking set */ 5248 sendbyte(&buf, 0x00); /* current tracking set */
5249 sendetx(&buf, parse); 5249 sendetx(&buf, parse);
5250 } 5250 }
5251} 5251}
5252 5252
5253/*-------------------------------------------------- 5253/*--------------------------------------------------
5254 * TRIMBLE TSIP end routine 5254 * TRIMBLE TSIP end routine
5255 */ 5255 */
5256static void 5256static void
5257trimbletsip_end( 5257trimbletsip_end(
5258 struct parseunit *parse 5258 struct parseunit *parse
5259 ) 5259 )
5260{ trimble_t *t = parse->localdata; 5260{ trimble_t *t = parse->localdata;
5261 5261
5262 if (t) 5262 if (t)
5263 { 5263 {
5264 free(t); 5264 free(t);
5265 parse->localdata = NULL; 5265 parse->localdata = NULL;
5266 } 5266 }
5267 parse->peer->procptr->nextaction = 0; 5267 parse->peer->procptr->nextaction = 0;
5268 parse->peer->procptr->action = NULL; 5268 parse->peer->procptr->action = NULL;
5269} 5269}
5270 5270
5271/*-------------------------------------------------- 5271/*--------------------------------------------------
5272 * TRIMBLE TSIP init routine 5272 * TRIMBLE TSIP init routine
5273 */ 5273 */
5274static int 5274static int
5275trimbletsip_init( 5275trimbletsip_init(
5276 struct parseunit *parse 5276 struct parseunit *parse
5277 ) 5277 )
5278{ 5278{
5279#if defined(VEOL) || defined(VEOL2) 5279#if defined(VEOL) || defined(VEOL2)
5280#ifdef HAVE_TERMIOS 5280#ifdef HAVE_TERMIOS
5281 struct termios tio; /* NEEDED FOR A LONG TIME ! */ 5281 struct termios tio; /* NEEDED FOR A LONG TIME ! */
5282#endif 5282#endif
5283#ifdef HAVE_SYSV_TTYS 5283#ifdef HAVE_SYSV_TTYS
5284 struct termio tio; /* NEEDED FOR A LONG TIME ! */ 5284 struct termio tio; /* NEEDED FOR A LONG TIME ! */
5285#endif 5285#endif
5286 /* 5286 /*
5287 * allocate local data area 5287 * allocate local data area
5288 */ 5288 */
5289 if (!parse->localdata) 5289 if (!parse->localdata)