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