| @@ -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 | |
211 | static char rcsid[] = "refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A+POWERUPTRUST"; | | 211 | static 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 | |
217 | static int parse_start (int, struct peer *); | | 217 | static int parse_start (int, struct peer *); |
218 | static void parse_shutdown (int, struct peer *); | | 218 | static void parse_shutdown (int, struct peer *); |
219 | static void parse_poll (int, struct peer *); | | 219 | static void parse_poll (int, struct peer *); |
220 | static void parse_control (int, const struct refclockstat *, struct refclockstat *, struct peer *); | | 220 | static void parse_control (int, const struct refclockstat *, struct refclockstat *, struct peer *); |
221 | | | 221 | |
222 | struct refclock refclock_parse = { | | 222 | struct 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 | |
249 | struct parseunit; /* to keep inquiring minds happy */ | | 249 | struct parseunit; /* to keep inquiring minds happy */ |
250 | | | 250 | |
251 | typedef struct bind | | 251 | typedef 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 | |
308 | struct errorregression | | 308 | struct 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 | |
314 | static struct errorregression | | 314 | static struct errorregression |
315 | err_baddata[] = /* error messages for bad input data */ | | 315 | err_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 | |
323 | static struct errorregression | | 323 | static struct errorregression |
324 | err_nodata[] = /* error messages for missing input data */ | | 324 | err_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 | |
332 | static struct errorregression | | 332 | static struct errorregression |
333 | err_badstatus[] = /* unsynchronized state messages */ | | 333 | err_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 | |
341 | static struct errorregression | | 341 | static struct errorregression |
342 | err_badio[] = /* io failures (bad reads, selects, ...) */ | | 342 | err_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 | |
350 | static struct errorregression | | 350 | static struct errorregression |
351 | err_badevent[] = /* non nominal events */ | | 351 | err_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 | |
359 | static struct errorregression | | 359 | static struct errorregression |
360 | err_internal[] = /* really bad things - basically coding/OS errors */ | | 360 | err_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 | |
365 | static struct errorregression * | | 365 | static struct errorregression * |
366 | err_tbl[] = | | 366 | err_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 | |
376 | struct errorinfo | | 376 | struct 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 | |
389 | struct parseunit | | 389 | struct 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 | |
444 | static void poll_dpoll (struct parseunit *); | | 444 | static void poll_dpoll (struct parseunit *); |
445 | static void poll_poll (struct peer *); | | 445 | static void poll_poll (struct peer *); |
446 | static int poll_init (struct parseunit *); | | 446 | static int poll_init (struct parseunit *); |
447 | | | 447 | |
448 | typedef struct poll_info | | 448 | typedef 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 | */ |
557 | static void gps16x_message (struct parseunit *, parsetime_t *); | | 557 | static void gps16x_message (struct parseunit *, parsetime_t *); |
558 | static int gps16x_poll_init (struct parseunit *); | | 558 | static 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 | |
576 | static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE }; | | 576 | static 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 | |
618 | static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE }; | | 618 | static 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 | */ |
698 | static int rawdcf_init_1 (struct parseunit *); | | 698 | static 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 | */ |
707 | static int rawdcf_init_2 (struct parseunit *); | | 707 | static 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 | |
722 | static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE }; | | 722 | static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE }; |
723 | static int trimbletaip_init (struct parseunit *); | | 723 | static int trimbletaip_init (struct parseunit *); |
724 | static void trimbletaip_event (struct parseunit *, int); | | 724 | static void trimbletaip_event (struct parseunit *, int); |
725 | | | 725 | |
726 | /* query time & UTC correction data */ | | 726 | /* query time & UTC correction data */ |
727 | static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX }; | | 727 | static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX }; |
728 | | | 728 | |
729 | static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) }; | | 729 | static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) }; |
730 | static int trimbletsip_init (struct parseunit *); | | 730 | static int trimbletsip_init (struct parseunit *); |
731 | static void trimbletsip_end (struct parseunit *); | | 731 | static void trimbletsip_end (struct parseunit *); |
732 | static void trimbletsip_message (struct parseunit *, parsetime_t *); | | 732 | static void trimbletsip_message (struct parseunit *, parsetime_t *); |
733 | static void trimbletsip_event (struct parseunit *, int); | | 733 | static 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 | |
802 | static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE }; | | 802 | static 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 | |
885 | static poll_info_t sel240x_pollinfo = { SEL240X_POLLRATE, | | 885 | static 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 | |
907 | static struct parse_clockinfo | | 907 | static 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 | */ |
3378 | static void | | 3378 | static void |
3379 | parse_ctl( | | 3379 | parse_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 | */ |
3438 | static void | | 3438 | static void |
3439 | parse_poll( | | 3439 | parse_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 | */ |
3493 | static void | | 3493 | static void |
3494 | parse_control( | | 3494 | parse_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 | */ |
3720 | static void | | 3720 | static void |
3721 | parse_event( | | 3721 | parse_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 | */ |
3748 | static void | | 3748 | static void |
3749 | parse_process( | | 3749 | parse_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 | |
4238 | static void | | 4238 | static void |
4239 | mk_utcinfo( | | 4239 | mk_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 | */ |
4303 | static void | | 4303 | static void |
4304 | gps16x_message( | | 4304 | gps16x_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 | */ |
4669 | static void | | 4669 | static void |
4670 | gps16x_poll( | | 4670 | gps16x_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 | */ |
4747 | static int | | 4747 | static int |
4748 | gps16x_poll_init( | | 4748 | gps16x_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 |
4762 | static void | | 4762 | static void |
4763 | gps16x_message( | | 4763 | gps16x_message( |
4764 | struct parseunit *parse, | | 4764 | struct parseunit *parse, |
4765 | parsetime_t *parsetime | | 4765 | parsetime_t *parsetime |
4766 | ) | | 4766 | ) |
4767 | {} | | 4767 | {} |
4768 | static int | | 4768 | static int |
4769 | gps16x_poll_init( | | 4769 | gps16x_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 | */ |
4784 | static void | | 4784 | static void |
4785 | poll_dpoll( | | 4785 | poll_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 | */ |
4811 | static void | | 4811 | static void |
4812 | poll_poll( | | 4812 | poll_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 | */ |
4830 | static int | | 4830 | static int |
4831 | poll_init( | | 4831 | poll_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 | */ |
4851 | static int | | 4851 | static int |
4852 | trimbletaip_init( | | 4852 | trimbletaip_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 | */ |
4886 | static const char *taipinit[] = { | | 4886 | static 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 | |
4893 | static void | | 4893 | static void |
4894 | trimbletaip_event( | | 4894 | trimbletaip_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 | |
5022 | typedef struct trimble | | 5022 | typedef 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 | |
5031 | union uval { | | 5031 | union 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 | |
5038 | struct txbuf | | 5038 | struct 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 | |
5044 | void sendcmd (struct txbuf *buf, int c); | | 5044 | void sendcmd (struct txbuf *buf, int c); |
5045 | void sendbyte (struct txbuf *buf, int b); | | 5045 | void sendbyte (struct txbuf *buf, int b); |
5046 | void sendetx (struct txbuf *buf, struct parseunit *parse); | | 5046 | void sendetx (struct txbuf *buf, struct parseunit *parse); |
5047 | void sendint (struct txbuf *buf, int a); | | 5047 | void sendint (struct txbuf *buf, int a); |
5048 | void sendflt (struct txbuf *buf, double a); | | 5048 | void sendflt (struct txbuf *buf, double a); |
5049 | | | 5049 | |
5050 | void | | 5050 | void |
5051 | sendcmd( | | 5051 | sendcmd( |
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 | |
5061 | void sendcmd (struct txbuf *buf, int c); | | 5061 | void sendcmd (struct txbuf *buf, int c); |
5062 | void sendbyte (struct txbuf *buf, int b); | | 5062 | void sendbyte (struct txbuf *buf, int b); |
5063 | void sendetx (struct txbuf *buf, struct parseunit *parse); | | 5063 | void sendetx (struct txbuf *buf, struct parseunit *parse); |
5064 | void sendint (struct txbuf *buf, int a); | | 5064 | void sendint (struct txbuf *buf, int a); |
5065 | void sendflt (struct txbuf *buf, double a); | | 5065 | void sendflt (struct txbuf *buf, double a); |
5066 | | | 5066 | |
5067 | void | | 5067 | void |
5068 | sendbyte( | | 5068 | sendbyte( |
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 | |
5078 | void | | 5078 | void |
5079 | sendetx( | | 5079 | sendetx( |
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 | |
5109 | void | | 5109 | void |
5110 | sendint( | | 5110 | sendint( |
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 | |
5120 | void | | 5120 | void |
5121 | sendflt( | | 5121 | sendflt( |
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 | */ |
5144 | static int | | 5144 | static int |
5145 | trimbletsip_setup( | | 5145 | trimbletsip_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 | */ |
5206 | static void | | 5206 | static void |
5207 | trimble_check( | | 5207 | trimble_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 | */ |
5256 | static void | | 5256 | static void |
5257 | trimbletsip_end( | | 5257 | trimbletsip_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 | */ |
5274 | static int | | 5274 | static int |
5275 | trimbletsip_init( | | 5275 | trimbletsip_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) |