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