xref: /netbsd-src/external/bsd/ntp/dist/libparse/clk_wharton.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: clk_wharton.c,v 1.7 2024/08/18 20:47:17 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * /src/NTP/ntp4-dev/libparse/clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A
5abb0f93cSkardel  *
6abb0f93cSkardel  * clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A
7abb0f93cSkardel  *
8abb0f93cSkardel  * From Philippe De Muyter <phdm@macqel.be>, 1999
9abb0f93cSkardel  */
10abb0f93cSkardel #ifdef HAVE_CONFIG_H
11abb0f93cSkardel #include <config.h>
12abb0f93cSkardel #endif
13abb0f93cSkardel 
14*eabc0478Schristos #include "ntp_types.h"
15*eabc0478Schristos 
16abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_WHARTON_400A)
17abb0f93cSkardel /*
18abb0f93cSkardel  * Support for WHARTON 400A Series clock + 404.2 serial interface.
19abb0f93cSkardel  */
20abb0f93cSkardel 
21abb0f93cSkardel #include "ntp_fp.h"
22abb0f93cSkardel #include "parse.h"
23abb0f93cSkardel 
24abb0f93cSkardel #ifndef PARSESTREAM
25abb0f93cSkardel #include "ntp_stdlib.h"
26abb0f93cSkardel #include <stdio.h>
27abb0f93cSkardel #else
28abb0f93cSkardel #include "sys/parsestreams.h"
29abb0f93cSkardel extern void printf (const char *, ...);
30abb0f93cSkardel #endif
31abb0f93cSkardel 
32*eabc0478Schristos #include "ascii.h"
33*eabc0478Schristos 
34abb0f93cSkardel /*
35abb0f93cSkardel  * In private e-mail alastair@wharton.co.uk said :
36abb0f93cSkardel  * "If you are going to use the 400A and 404.2 system [for ntp] I recommend
37abb0f93cSkardel  * that you set the 400A to output the message every second.  The start of
38abb0f93cSkardel  * transmission of the first byte of the message is synchronised to the
39abb0f93cSkardel  * second edge."
40abb0f93cSkardel  * The WHARTON 400A Series is able to send date/time serial messages
41abb0f93cSkardel  * in 7 output formats.  We use format 1 here because it is the shortest.
42abb0f93cSkardel  * For use with this driver, the WHARTON 400A Series clock must be set-up
43abb0f93cSkardel  * as follows :
44abb0f93cSkardel  *					Programmable	Selected
45abb0f93cSkardel  *					Option No	Option
46abb0f93cSkardel  *	BST or CET display		3		9 or 11
47abb0f93cSkardel  *	No external controller		7		0
48abb0f93cSkardel  *	Serial Output Format 1		9		1
49abb0f93cSkardel  *	Baud rate 9600 bps		10		96
50abb0f93cSkardel  *	Bit length 8 bits		11		8
51abb0f93cSkardel  *	Parity even			12		E
52abb0f93cSkardel  *
53abb0f93cSkardel  * WHARTON 400A Series output format 1 is as follows :
54abb0f93cSkardel  *
55abb0f93cSkardel  * Timestamp	STXssmmhhDDMMYYSETX
56abb0f93cSkardel  * Pos		0  12345678901234
57abb0f93cSkardel  *		0  00000000011111
58abb0f93cSkardel  *
59abb0f93cSkardel  *	STX	start transmission (ASCII 0x02)
60abb0f93cSkardel  *	ETX	end transmission (ASCII 0x03)
61abb0f93cSkardel  *	ss	Second expressed in reversed decimal (units then tens)
62abb0f93cSkardel  *	mm	Minute expressed in reversed decimal
63abb0f93cSkardel  *	hh	Hour expressed in reversed decimal
64abb0f93cSkardel  *	DD	Day of month expressed in reversed decimal
65abb0f93cSkardel  *	MM	Month expressed in reversed decimal (January is 1)
66abb0f93cSkardel  *	YY	Year (without century) expressed in reversed decimal
67abb0f93cSkardel  *	S	Status byte : 0x30 +
68abb0f93cSkardel  *			bit 0	0 = MSF source		1 = DCF source
69abb0f93cSkardel  *			bit 1	0 = Winter time		1 = Summer time
70abb0f93cSkardel  *			bit 2	0 = not synchronised	1 = synchronised
71abb0f93cSkardel  *			bit 3	0 = no early warning	1 = early warning
72abb0f93cSkardel  *
73abb0f93cSkardel  */
74abb0f93cSkardel 
757476e6e4Schristos static parse_cvt_fnc_t cvt_wharton_400a;
767476e6e4Schristos static parse_inp_fnc_t inp_wharton_400a;
777476e6e4Schristos 
78abb0f93cSkardel /*
797476e6e4Schristos  * parse_cvt_fnc_t cvt_wharton_400a
80abb0f93cSkardel  *
81abb0f93cSkardel  * convert simple type format
82abb0f93cSkardel  */
83abb0f93cSkardel static          u_long
84abb0f93cSkardel cvt_wharton_400a(
85abb0f93cSkardel 	unsigned char *buffer,
86abb0f93cSkardel 	int            size,
87abb0f93cSkardel 	struct format *format,
88abb0f93cSkardel 	clocktime_t   *clock_time,
89abb0f93cSkardel 	void          *local
90abb0f93cSkardel 	)
91abb0f93cSkardel {
92abb0f93cSkardel 	int	i;
93abb0f93cSkardel 
94abb0f93cSkardel 	/* The given `size' includes a terminating null-character. */
958585484eSchristos 	if (size != 15 || buffer[0] != STX || buffer[14] != ETX
96abb0f93cSkardel 	    || buffer[13] < '0' || buffer[13] > ('0' + 0xf))
97abb0f93cSkardel 		return CVT_NONE;
98abb0f93cSkardel 	for (i = 1; i < 13; i += 1)
99abb0f93cSkardel 		if (buffer[i] < '0' || buffer[i] > '9')
100abb0f93cSkardel 			return CVT_NONE;
101abb0f93cSkardel 	clock_time->second = (buffer[2] - '0') * 10 + buffer[1] - '0';
102abb0f93cSkardel 	clock_time->minute = (buffer[4] - '0') * 10 + buffer[3] - '0';
103abb0f93cSkardel 	clock_time->hour   = (buffer[6] - '0') * 10 + buffer[5] - '0';
104abb0f93cSkardel 	clock_time->day    = (buffer[8] - '0') * 10 + buffer[7] - '0';
105abb0f93cSkardel 	clock_time->month  = (buffer[10] - '0') * 10 + buffer[9] - '0';
106abb0f93cSkardel 	clock_time->year   = (buffer[12] - '0') * 10 + buffer[11] - '0';
107abb0f93cSkardel 	clock_time->usecond = 0;
108abb0f93cSkardel 	if (buffer[13] & 0x1) /* We have CET time */
109abb0f93cSkardel 		clock_time->utcoffset = -1*60*60;
110abb0f93cSkardel 	else		/* We have BST time */
111abb0f93cSkardel 		clock_time->utcoffset = 0;
112abb0f93cSkardel 	if (buffer[13] & 0x2) {
113abb0f93cSkardel 		clock_time->flags |= PARSEB_DST;
114abb0f93cSkardel 		clock_time->utcoffset += -1*60*60;
115abb0f93cSkardel 	}
116abb0f93cSkardel 	if (!(buffer[13] & 0x4))
117abb0f93cSkardel 		clock_time->flags |= PARSEB_NOSYNC;
118abb0f93cSkardel 	if (buffer[13] & 0x8)
119abb0f93cSkardel 		clock_time->flags |= PARSEB_ANNOUNCE;
120abb0f93cSkardel 
121abb0f93cSkardel 	return CVT_OK;
122abb0f93cSkardel }
123abb0f93cSkardel 
124abb0f93cSkardel /*
1257476e6e4Schristos  * parse_inp_fnc_t inp_wharton_400a
126abb0f93cSkardel  *
1277476e6e4Schristos  * grab data from input stream
128abb0f93cSkardel  */
129abb0f93cSkardel static u_long
130abb0f93cSkardel inp_wharton_400a(
131abb0f93cSkardel 	      parse_t      *parseio,
1327476e6e4Schristos 	      char         ch,
133abb0f93cSkardel 	      timestamp_t  *tstamp
134abb0f93cSkardel 	      )
135abb0f93cSkardel {
136abb0f93cSkardel 	unsigned int rtc;
137abb0f93cSkardel 
1388b8da087Schristos 	parseprintf(DD_PARSE, ("inp_wharton_400a(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
139abb0f93cSkardel 
140abb0f93cSkardel 	switch (ch)
141abb0f93cSkardel 	{
142abb0f93cSkardel 	case STX:
143abb0f93cSkardel 		parseprintf(DD_PARSE, ("inp_wharton_400a: STX seen\n"));
144abb0f93cSkardel 
145abb0f93cSkardel 		parseio->parse_index = 1;
146abb0f93cSkardel 		parseio->parse_data[0] = ch;
147abb0f93cSkardel 		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
148abb0f93cSkardel 		return PARSE_INP_SKIP;
149abb0f93cSkardel 
150abb0f93cSkardel 	case ETX:
151abb0f93cSkardel 		parseprintf(DD_PARSE, ("inp_wharton_400a: ETX seen\n"));
152abb0f93cSkardel 		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
153abb0f93cSkardel 			return parse_end(parseio);
154abb0f93cSkardel 		else
155abb0f93cSkardel 			return rtc;
156abb0f93cSkardel 
157abb0f93cSkardel 	default:
158abb0f93cSkardel 		return parse_addchar(parseio, ch);
159abb0f93cSkardel 	}
160abb0f93cSkardel }
161abb0f93cSkardel 
162abb0f93cSkardel clockformat_t   clock_wharton_400a =
163abb0f93cSkardel {
164abb0f93cSkardel 	inp_wharton_400a,	/* input handling function */
165abb0f93cSkardel 	cvt_wharton_400a,	/* conversion function */
166abb0f93cSkardel 	0,			/* no PPS monitoring */
167abb0f93cSkardel 	0,			/* conversion configuration */
168abb0f93cSkardel 	"WHARTON 400A Series clock Output Format 1",	/* String format name */
169abb0f93cSkardel 	15,			/* string buffer */
1707476e6e4Schristos 	0			/* no private data (complete packets) */
171abb0f93cSkardel };
172abb0f93cSkardel 
173abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */
174*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT
175abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */
176abb0f93cSkardel 
177abb0f93cSkardel /*
178abb0f93cSkardel  * clk_wharton.c,v
179abb0f93cSkardel  * Revision 4.1  1999/02/28 15:27:24  kardel
180abb0f93cSkardel  * wharton clock integration
181abb0f93cSkardel  *
182abb0f93cSkardel  */
183