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