clk_hopf6021.c revision 56746
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"
40extern 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
105static 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
124static unsigned long cvt_hopf6021 P((unsigned char *, int, struct format *, clocktime_t *, void *));
125static unsigned long inp_hopf6021 P((parse_t *, unsigned int, timestamp_t *));
126
127clockformat_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
138static unsigned long
139cvt_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 */
223static u_long
224inp_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) */
250int 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