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