1 /*
2 * /src/NTP/ntp4-dev/libparse/clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
3 *
4 * clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
5 *
6 * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle
7 * base code version from 24th Nov 1995 - history at end
8 *
9 * Created by F.Schnekenbuehl <frank@comsys.dofn.de> from clk_rcc8000.c
10 * Nortel DASA Network Systems GmbH, Department: ND250
11 * A Joint venture of Daimler-Benz Aerospace and Nortel
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include "ntp_types.h"
24
25 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021)
26
27 #include "ntp_fp.h"
28 #include "ntp_unixtime.h"
29 #include "ntp_calendar.h"
30
31 #include "parse.h"
32
33 #ifndef PARSESTREAM
34 #include "ntp_stdlib.h"
35 #include <stdio.h>
36 #else
37 #include "sys/parsestreams.h"
38 extern int printf (const char *, ...);
39 #endif
40
41 #include "ascii.h"
42
43 /*
44 * hopf Funkuhr 6021
45 * used with 9600,8N1,
46 * UTC ueber serielle Schnittstelle
47 * Sekundenvorlauf ON
48 * ETX zum Sekundenvorlauf ON
49 * Datenstring 6021
50 * Ausgabe Uhrzeit und Datum
51 * Senden mit Steuerzeichen
52 * Senden sekuendlich
53 */
54
55 /*
56 * Type 6021 Serial Output format
57 *
58 * 000000000011111111 / char
59 * 012345678901234567 \ position
60 * sABHHMMSSDDMMYYnre Actual
61 * C4110046231195 Parse
62 * s enr Check
63 *
64 * s = STX (0x02), e = ETX (0x03)
65 * n = NL (0x0A), r = CR (0x0D)
66 *
67 * A B - Status and weekday
68 *
69 * A - Status
70 *
71 * 8 4 2 1
72 * x x x 0 - no announcement
73 * x x x 1 - Summertime - wintertime - summertime announcement
74 * x x 0 x - Wintertime
75 * x x 1 x - Summertime
76 * 0 0 x x - Time/Date invalid
77 * 0 1 x x - Internal clock used
78 * 1 0 x x - Radio clock
79 * 1 1 x x - Radio clock highprecision
80 *
81 * B - 8 4 2 1
82 * 0 x x x - MESZ/MEZ
83 * 1 x x x - UTC
84 * x 0 0 1 - Monday
85 * x 0 1 0 - Tuesday
86 * x 0 1 1 - Wednesday
87 * x 1 0 0 - Thursday
88 * x 1 0 1 - Friday
89 * x 1 1 0 - Saturday
90 * x 1 1 1 - Sunday
91 */
92
93 #define HOPF_DSTWARN 0x01 /* DST switch warning */
94 #define HOPF_DST 0x02 /* DST in effect */
95
96 #define HOPF_MODE 0x0C /* operation mode mask */
97 #define HOPF_INVALID 0x00 /* no time code available */
98 #define HOPF_INTERNAL 0x04 /* internal clock */
99 #define HOPF_RADIO 0x08 /* radio clock */
100 #define HOPF_RADIOHP 0x0C /* high precision radio clock */
101
102 #define HOPF_UTC 0x08 /* time code in UTC */
103 #define HOPF_WMASK 0x07 /* mask for weekday code */
104
105 static struct format hopf6021_fmt =
106 {
107 {
108 { 9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */
109 { 3, 2 }, { 5, 2}, { 7, 2}, /* Hour, Minute, Second */
110 { 2, 1 }, { 1, 1}, { 0, 0}, /* Weekday, Flags, Zone */
111 /* ... */
112 },
113 (const unsigned char *)"\002 \n\r\003",
114 0
115 };
116
117 #define OFFS(x) format->field_offsets[(x)].offset
118 #define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length)
119
120 static parse_cvt_fnc_t cvt_hopf6021;
121 static parse_inp_fnc_t inp_hopf6021;
122 static unsigned char hexval(unsigned char);
123
124 clockformat_t clock_hopf6021 =
125 {
126 inp_hopf6021, /* HOPF 6021 input handling */
127 cvt_hopf6021, /* Radiocode clock conversion */
128 0, /* no direct PPS monitoring */
129 (void *)&hopf6021_fmt, /* conversion configuration */
130 "hopf Funkuhr 6021", /* clock format name */
131 19, /* string buffer */
132 0 /* private data length, no private data */
133 };
134
135 /* parse_cvt_fnc_t cvt_hopf6021 */
136 static u_long
cvt_hopf6021(unsigned char * buffer,int size,struct format * format,clocktime_t * clock_time,void * local)137 cvt_hopf6021(
138 unsigned char *buffer,
139 int size,
140 struct format *format,
141 clocktime_t *clock_time,
142 void *local
143 )
144 {
145 unsigned char status,weekday;
146
147 if (!Strok(buffer, format->fixed_string))
148 {
149 return CVT_NONE;
150 }
151
152 if ( STOI(O_DAY, &clock_time->day) ||
153 STOI(O_MONTH, &clock_time->month) ||
154 STOI(O_YEAR, &clock_time->year) ||
155 STOI(O_HOUR, &clock_time->hour) ||
156 STOI(O_MIN, &clock_time->minute) ||
157 STOI(O_SEC, &clock_time->second)
158 )
159 {
160 return CVT_FAIL|CVT_BADFMT;
161 }
162
163 clock_time->usecond = 0;
164 clock_time->flags = 0;
165
166 status = hexval(buffer[OFFS(O_FLAGS)]);
167 weekday = hexval(buffer[OFFS(O_WDAY)]);
168
169 if ((status == 0xFF) || (weekday == 0xFF))
170 {
171 return CVT_FAIL|CVT_BADFMT;
172 }
173
174 if (weekday & HOPF_UTC)
175 {
176 clock_time->flags |= PARSEB_UTC;
177 clock_time->utcoffset = 0;
178 }
179 else if (status & HOPF_DST)
180 {
181 clock_time->flags |= PARSEB_DST;
182 clock_time->utcoffset = -2*60*60; /* MET DST */
183 }
184 else
185 {
186 clock_time->utcoffset = -1*60*60; /* MET */
187 }
188
189 if (status & HOPF_DSTWARN)
190 {
191 clock_time->flags |= PARSEB_ANNOUNCE;
192 }
193
194 switch (status & HOPF_MODE)
195 {
196 default: /* dummy: we cover all 4 cases. */
197 case HOPF_INVALID: /* Time/Date invalid */
198 clock_time->flags |= PARSEB_POWERUP;
199 break;
200
201 case HOPF_INTERNAL: /* internal clock */
202 clock_time->flags |= PARSEB_NOSYNC;
203 break;
204
205 case HOPF_RADIO: /* Radio clock */
206 case HOPF_RADIOHP: /* Radio clock high precision */
207 break;
208 }
209
210 return CVT_OK;
211 }
212
213 /*
214 * parse_inp_fnc_t inp_hopf6021
215 *
216 * grab data from input stream
217 */
218 static u_long
inp_hopf6021(parse_t * parseio,char ch,timestamp_t * tstamp)219 inp_hopf6021(
220 parse_t *parseio,
221 char ch,
222 timestamp_t *tstamp
223 )
224 {
225 unsigned int rtc;
226
227 parseprintf(DD_PARSE, ("inp_hopf6021(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
228
229 switch (ch)
230 {
231 case ETX:
232 parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
233 parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
234 if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
235 return parse_end(parseio);
236 else
237 return rtc;
238
239 default:
240 return parse_addchar(parseio, ch);
241 }
242 }
243
244 /*
245 * convert a hex-digit to numeric value
246 */
247 static unsigned char
hexval(unsigned char ch)248 hexval(
249 unsigned char ch
250 )
251 {
252 unsigned int dv;
253
254 if ((dv = ch - '0') >= 10u)
255 {
256 if ((dv -= 'A'-'0') < 6u || (dv -= 'a'-'A') < 6u)
257 {
258 dv += 10;
259 }
260 else
261 {
262 dv = 0xFF;
263 }
264 }
265 return (unsigned char)dv;
266 }
267
268 #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
269 NONEMPTY_TRANSLATION_UNIT
270 #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
271
272 /*
273 * History:
274 *
275 * clk_hopf6021.c,v
276 * Revision 4.10 2004/11/14 15:29:41 kardel
277 * support PPSAPI, upgrade Copyright to Berkeley style
278 *
279 * Revision 4.7 1999/11/28 09:13:49 kardel
280 * RECON_4_0_98F
281 *
282 * Revision 4.6 1998/11/15 20:27:57 kardel
283 * Release 4.0.73e13 reconcilation
284 *
285 * Revision 4.5 1998/06/14 21:09:35 kardel
286 * Sun acc cleanup
287 *
288 * Revision 4.4 1998/06/13 12:02:38 kardel
289 * fix SYSV clock name clash
290 *
291 * Revision 4.3 1998/06/12 15:22:27 kardel
292 * fix prototypes
293 *
294 * Revision 4.2 1998/06/12 09:13:25 kardel
295 * conditional compile macros fixed
296 * printf prototype
297 *
298 * Revision 4.1 1998/05/24 09:39:52 kardel
299 * implementation of the new IO handling model
300 *
301 * Revision 4.0 1998/04/10 19:45:29 kardel
302 * Start 4.0 release version numbering
303 *
304 * from V3 3.6 log info deleted 1998/04/11 kardel
305 */
306