clk_schmid.c revision 54359
1/*
2 * /src/NTP/ntp-4/libparse/clk_schmid.c,v 4.4 1998/06/13 12:06:03 kardel RELEASE_19990228_A
3 *
4 * clk_schmid.c,v 4.4 1998/06/13 12:06:03 kardel RELEASE_19990228_A
5 *
6 * Schmid clock support
7 *
8 * Copyright (C) 1992-1998 by Frank Kardel
9 * Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 */
16
17#if HAVE_CONFIG_H
18# include <config.h>
19#endif
20
21#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID)
22
23#include <sys/types.h>
24#include <sys/time.h>
25
26#include "ntp_fp.h"
27#include "ntp_unixtime.h"
28#include "ntp_calendar.h"
29
30#include "parse.h"
31
32#ifndef PARSESTREAM
33#include "ntp_stdlib.h"
34#include <stdio.h>
35#else
36#include "sys/parsestreams.h"
37extern void printf P((const char *, ...));
38#endif
39
40/*
41 * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch)
42 *
43 * The command to Schmid's DCF77 clock is a single byte; each bit
44 * allows the user to select some part of the time string, as follows (the
45 * output for the lsb is sent first).
46 *
47 * Bit 0:	time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths
48 * Bit 1:	date 3 bytes *binary, not BCD: dd.mm.yy
49 * Bit 2:	week day, 1 byte (unused here)
50 * Bit 3:	time zone, 1 byte, 0=MET, 1=MEST. (unused here)
51 * Bit 4:	clock status, 1 byte,	0=time invalid,
52 *					1=time from crystal backup,
53 *					3=time from DCF77
54 * Bit 5:	transmitter status, 1 byte,
55 *					bit 0: backup antenna
56 *					bit 1: time zone change within 1h
57 *					bit 3,2: TZ 01=MEST, 10=MET
58 *					bit 4: leap second will be
59 *						added within one hour
60 *					bits 5-7: Zero
61 * Bit 6:	time in backup mode, units of 5 minutes (unused here)
62 *
63 */
64#define WS_TIME		0x01
65#define WS_SIGNAL	0x02
66
67#define WS_ALTERNATE	0x01
68#define WS_ANNOUNCE	0x02
69#define WS_TZ		0x0c
70#define   WS_MET	0x08
71#define   WS_MEST	0x04
72#define WS_LEAP		0x10
73
74static u_long cvt_schmid P((unsigned char *, int, struct format *, clocktime_t *, void *));
75static unsigned long inp_schmid P((parse_t *, unsigned int, timestamp_t *));
76
77clockformat_t clock_schmid =
78{
79  inp_schmid,			/* no input handling */
80  cvt_schmid,			/* Schmid conversion */
81  0,				/* not direct PPS monitoring */
82  0,				/* conversion configuration */
83  "Schmid",			/* Schmid receiver */
84  12,				/* binary data buffer */
85  0,				/* no private data (complete messages) */
86};
87
88
89static u_long
90cvt_schmid(
91	   unsigned char *buffer,
92	   int            size,
93	   struct format *format,
94	   clocktime_t   *clock_time,
95	   void          *local
96	)
97{
98	if ((size != 11) || (buffer[10] != (unsigned char)'\375'))
99	{
100		return CVT_NONE;
101	}
102	else
103	{
104		if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] >  9) /* Time */
105		{
106			return CVT_FAIL|CVT_BADTIME;
107		}
108		else
109		    if (buffer[4] <  1 || buffer[4] > 31 || buffer[5] <  1 || buffer[5] > 12
110			||  buffer[6] > 99)
111		    {
112			    return CVT_FAIL|CVT_BADDATE;
113		    }
114		    else
115		    {
116			    clock_time->hour    = buffer[0];
117			    clock_time->minute  = buffer[1];
118			    clock_time->second  = buffer[2];
119			    clock_time->usecond = buffer[3] * 100000;
120			    clock_time->day     = buffer[4];
121			    clock_time->month   = buffer[5];
122			    clock_time->year    = buffer[6];
123
124			    clock_time->flags   = 0;
125
126			    switch (buffer[8] & WS_TZ)
127			    {
128				case WS_MET:
129				    clock_time->utcoffset = -1*60*60;
130				    break;
131
132				case WS_MEST:
133				    clock_time->utcoffset = -2*60*60;
134				    clock_time->flags    |= PARSEB_DST;
135				    break;
136
137				default:
138				    return CVT_FAIL|CVT_BADFMT;
139			    }
140
141			    if (!(buffer[7] & WS_TIME))
142			    {
143				    clock_time->flags |= PARSEB_POWERUP;
144			    }
145
146			    if (!(buffer[7] & WS_SIGNAL))
147			    {
148				    clock_time->flags |= PARSEB_NOSYNC;
149			    }
150
151			    if (buffer[7] & WS_SIGNAL)
152			    {
153				    if (buffer[8] & WS_ALTERNATE)
154				    {
155					    clock_time->flags |= PARSEB_ALTERNATE;
156				    }
157
158				    if (buffer[8] & WS_ANNOUNCE)
159				    {
160					    clock_time->flags |= PARSEB_ANNOUNCE;
161				    }
162
163				    if (buffer[8] & WS_LEAP)
164				    {
165					    clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */
166				    }
167			    }
168
169			    clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA;
170
171			    return CVT_OK;
172		    }
173	}
174}
175
176/*
177 * inp_schmid
178 *
179 * grep data from input stream
180 */
181static u_long
182inp_schmid(
183	  parse_t      *parseio,
184	  unsigned int  ch,
185	  timestamp_t  *tstamp
186	  )
187{
188	unsigned int rtc;
189
190	parseprintf(DD_PARSE, ("inp_schmid(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch));
191
192	switch (ch)
193	{
194	case 0xFD:		/*  */
195		parseprintf(DD_PARSE, ("mbg_input: ETX seen\n"));
196		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
197			return parse_end(parseio);
198		else
199			return rtc;
200
201	default:
202		return parse_addchar(parseio, ch);
203	}
204}
205
206#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */
207int clk_schmid_bs;
208#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */
209
210/*
211 * History:
212 *
213 * clk_schmid.c,v
214 * Revision 4.4  1998/06/13 12:06:03  kardel
215 * fix SYSV clock name clash
216 *
217 * Revision 4.3  1998/06/12 15:22:29  kardel
218 * fix prototypes
219 *
220 * Revision 4.2  1998/06/12 09:13:26  kardel
221 * conditional compile macros fixed
222 * printf prototype
223 *
224 * Revision 4.1  1998/05/24 09:39:53  kardel
225 * implementation of the new IO handling model
226 *
227 * Revision 4.0  1998/04/10 19:45:31  kardel
228 * Start 4.0 release version numbering
229 *
230 * from V3 3.22 log info deleted 1998/04/11 kardel
231 */
232