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