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