clk_schmid.c revision 56746
1169691Skan/*
2169691Skan * /src/NTP/ntp-4/libparse/clk_schmid.c,v 4.5 1999/11/28 09:13:51 kardel RELEASE_19991128_A
3169691Skan *
4169691Skan * clk_schmid.c,v 4.5 1999/11/28 09:13:51 kardel RELEASE_19991128_A
5169691Skan *
6169691Skan * Schmid clock support
7169691Skan *
8169691Skan * Copyright (C) 1992-1998 by Frank Kardel
9169691Skan * Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany
10169691Skan *
11169691Skan * This program is distributed in the hope that it will be useful,
12169691Skan * but WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14169691Skan *
15169691Skan */
16169691Skan
17169691Skan#if HAVE_CONFIG_H
18169691Skan# include <config.h>
19169691Skan#endif
20169691Skan
21169691Skan#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID)
22169691Skan
23169691Skan#include <sys/types.h>
24169691Skan#include <sys/time.h>
25169691Skan
26169691Skan#include "ntp_fp.h"
27169691Skan#include "ntp_unixtime.h"
28169691Skan#include "ntp_calendar.h"
29169691Skan
30169691Skan#include "parse.h"
31169691Skan
32169691Skan#ifndef PARSESTREAM
33169691Skan#include "ntp_stdlib.h"
34169691Skan#include <stdio.h>
35169691Skan#else
36169691Skan#include "sys/parsestreams.h"
37169691Skanextern void printf P((const char *, ...));
38169691Skan#endif
39169691Skan
40169691Skan/*
41169691Skan * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch)
42169691Skan *
43169691Skan * The command to Schmid's DCF77 clock is a single byte; each bit
44169691Skan * allows the user to select some part of the time string, as follows (the
45228780Spfg * output for the lsb is sent first).
46169691Skan *
47169691Skan * Bit 0:	time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths
48169691Skan * Bit 1:	date 3 bytes *binary, not BCD: dd.mm.yy
49169691Skan * Bit 2:	week day, 1 byte (unused here)
50169691Skan * Bit 3:	time zone, 1 byte, 0=MET, 1=MEST. (unused here)
51169691Skan * Bit 4:	clock status, 1 byte,	0=time invalid,
52169691Skan *					1=time from crystal backup,
53169691Skan *					3=time from DCF77
54169691Skan * Bit 5:	transmitter status, 1 byte,
55169691Skan *					bit 0: backup antenna
56169691Skan *					bit 1: time zone change within 1h
57169691Skan *					bit 3,2: TZ 01=MEST, 10=MET
58169691Skan *					bit 4: leap second will be
59169691Skan *						added within one hour
60169691Skan *					bits 5-7: Zero
61169691Skan * Bit 6:	time in backup mode, units of 5 minutes (unused here)
62169691Skan *
63169691Skan */
64169691Skan#define WS_TIME		0x01
65169691Skan#define WS_SIGNAL	0x02
66169691Skan
67169691Skan#define WS_ALTERNATE	0x01
68169691Skan#define WS_ANNOUNCE	0x02
69169691Skan#define WS_TZ		0x0c
70169691Skan#define   WS_MET	0x08
71169691Skan#define   WS_MEST	0x04
72169691Skan#define WS_LEAP		0x10
73169691Skan
74169691Skanstatic u_long cvt_schmid P((unsigned char *, int, struct format *, clocktime_t *, void *));
75169691Skanstatic unsigned long inp_schmid P((parse_t *, unsigned int, timestamp_t *));
76169691Skan
77169691Skanclockformat_t clock_schmid =
78169691Skan{
79169691Skan  inp_schmid,			/* no input handling */
80169691Skan  cvt_schmid,			/* Schmid conversion */
81169691Skan  0,				/* not direct PPS monitoring */
82169691Skan  0,				/* conversion configuration */
83169691Skan  "Schmid",			/* Schmid receiver */
84169691Skan  12,				/* binary data buffer */
85169691Skan  0,				/* no private data (complete messages) */
86169691Skan};
87169691Skan
88169691Skan
89169691Skanstatic u_long
90169691Skancvt_schmid(
91169691Skan	   unsigned char *buffer,
92169691Skan	   int            size,
93169691Skan	   struct format *format,
94169691Skan	   clocktime_t   *clock_time,
95169691Skan	   void          *local
96169691Skan	)
97169691Skan{
98169691Skan	if ((size != 11) || (buffer[10] != (unsigned char)'\375'))
99169691Skan	{
100169691Skan		return CVT_NONE;
101169691Skan	}
102169691Skan	else
103169691Skan	{
104169691Skan		if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] >  9) /* Time */
105169691Skan		{
106169691Skan			return CVT_FAIL|CVT_BADTIME;
107169691Skan		}
108169691Skan		else
109169691Skan		    if (buffer[4] <  1 || buffer[4] > 31 || buffer[5] <  1 || buffer[5] > 12
110169691Skan			||  buffer[6] > 99)
111169691Skan		    {
112169691Skan			    return CVT_FAIL|CVT_BADDATE;
113169691Skan		    }
114169691Skan		    else
115169691Skan		    {
116169691Skan			    clock_time->hour    = buffer[0];
117169691Skan			    clock_time->minute  = buffer[1];
118169691Skan			    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.5  1999/11/28 09:13:51  kardel
215 * RECON_4_0_98F
216 *
217 * Revision 4.4  1998/06/13 12:06:03  kardel
218 * fix SYSV clock name clash
219 *
220 * Revision 4.3  1998/06/12 15:22:29  kardel
221 * fix prototypes
222 *
223 * Revision 4.2  1998/06/12 09:13:26  kardel
224 * conditional compile macros fixed
225 * printf prototype
226 *
227 * Revision 4.1  1998/05/24 09:39:53  kardel
228 * implementation of the new IO handling model
229 *
230 * Revision 4.0  1998/04/10 19:45:31  kardel
231 * Start 4.0 release version numbering
232 *
233 * from V3 3.22 log info deleted 1998/04/11 kardel
234 */
235