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