clk_varitext.c revision 1.5 1 1.5 christos /* $NetBSD: clk_varitext.c,v 1.5 2016/01/08 21:35:39 christos Exp $ */
2 1.1 kardel
3 1.1 kardel #ifdef HAVE_CONFIG_H
4 1.1 kardel # include <config.h>
5 1.1 kardel #endif
6 1.1 kardel
7 1.1 kardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_VARITEXT)
8 1.1 kardel /*
9 1.1 kardel * /src/NTP/ntp4-dev/libparse/clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A
10 1.1 kardel *
11 1.1 kardel * clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A
12 1.1 kardel *
13 1.1 kardel * Varitext code variant by A.McConnell 1997/01/19
14 1.3 christos *
15 1.1 kardel * Supports Varitext's Radio Clock
16 1.3 christos *
17 1.1 kardel * Used the Meinberg/Computime clock as a template for Varitext Radio Clock
18 1.1 kardel *
19 1.1 kardel * Codebase:
20 1.1 kardel * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
21 1.3 christos * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
22 1.1 kardel *
23 1.1 kardel * Redistribution and use in source and binary forms, with or without
24 1.1 kardel * modification, are permitted provided that the following conditions
25 1.1 kardel * are met:
26 1.1 kardel * 1. Redistributions of source code must retain the above copyright
27 1.1 kardel * notice, this list of conditions and the following disclaimer.
28 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright
29 1.1 kardel * notice, this list of conditions and the following disclaimer in the
30 1.1 kardel * documentation and/or other materials provided with the distribution.
31 1.1 kardel * 3. Neither the name of the author nor the names of its contributors
32 1.1 kardel * may be used to endorse or promote products derived from this software
33 1.1 kardel * without specific prior written permission.
34 1.1 kardel *
35 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 1.1 kardel * SUCH DAMAGE.
46 1.1 kardel *
47 1.1 kardel */
48 1.1 kardel
49 1.1 kardel #include "ntp_fp.h"
50 1.1 kardel #include "ntp_unixtime.h"
51 1.1 kardel #include "ntp_calendar.h"
52 1.1 kardel
53 1.1 kardel #include "parse.h"
54 1.1 kardel
55 1.1 kardel #ifndef PARSESTREAM
56 1.1 kardel # include "ntp_stdlib.h"
57 1.1 kardel # include <stdio.h>
58 1.1 kardel #else
59 1.1 kardel # include "sys/parsestreams.h"
60 1.1 kardel extern int printf (const char *, ...);
61 1.1 kardel #endif
62 1.1 kardel
63 1.5 christos /* static const u_char VT_INITIALISED = 0x01; */
64 1.5 christos /* static const u_char VT_SYNCHRONISED = 0x02; */
65 1.5 christos /* static const u_char VT_ALARM_STATE = 0x04; */
66 1.1 kardel static const u_char VT_BST = 0x08;
67 1.5 christos /* static const u_char VT_SEASON_CHANGE = 0x10; */
68 1.5 christos /* static const u_char VT_LAST_TELEGRAM_OK = 0x20; */
69 1.1 kardel
70 1.1 kardel /*
71 1.1 kardel * The Varitext receiver sends a datagram in the following format every minute
72 1.3 christos *
73 1.3 christos * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLFSTXXX
74 1.1 kardel * Pos 0123456789012345678901 2 3 4567
75 1.1 kardel * 0000000000111111111122 2 2 2222
76 1.3 christos * Parse T: : : : : : : \r\n
77 1.3 christos *
78 1.3 christos * T Startcharacter "T" specifies start of the timestamp
79 1.3 christos * YY Year MM Month 1-12
80 1.3 christos * MD Day of the month
81 1.3 christos * WD Day of week
82 1.3 christos * HH Hour
83 1.3 christos * MM Minute
84 1.3 christos * SS Second
85 1.3 christos * CR Carriage return
86 1.3 christos * LF Linefeed
87 1.1 kardel * ST Status character
88 1.1 kardel * Bit 0 - Set= Initialised; Reset=Time Invalid (DO NOT USE)
89 1.3 christos * Bit 1 - Set= Synchronised; Reset= Unsynchronised
90 1.3 christos * Bit 2 - Set= Alarm state; Reset= No alarm
91 1.3 christos * Bit 3 - Set= BST; Reset= GMT
92 1.3 christos * Bit 4 - Set= Seasonal change in approx hour; Reset= No seasonal change expected
93 1.1 kardel * Bit 5 - Set= Last MSF telegram was OK; Reset= Last telegram was in error;
94 1.3 christos * Bit 6 - Always set
95 1.1 kardel * Bit 7 - Unused
96 1.3 christos * XXX Checksum calculated using Fletcher's method (ignored for now).
97 1.1 kardel */
98 1.1 kardel
99 1.1 kardel static struct format varitext_fmt =
100 1.1 kardel {
101 1.1 kardel {
102 1.1 kardel {8, 2}, {5, 2}, {2, 2}, /* day, month, year */
103 1.1 kardel {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */
104 1.1 kardel {11, 2}, {24, 1} /* dayofweek, status */
105 1.1 kardel },
106 1.1 kardel (const unsigned char*)"T: : : : : : : \r\n ",
107 1.1 kardel 0
108 1.1 kardel };
109 1.1 kardel
110 1.3 christos static parse_cvt_fnc_t cvt_varitext;
111 1.3 christos static parse_inp_fnc_t inp_varitext;
112 1.1 kardel
113 1.1 kardel struct varitext {
114 1.1 kardel unsigned char start_found;
115 1.1 kardel unsigned char end_found;
116 1.1 kardel unsigned char end_count;
117 1.1 kardel unsigned char previous_ch;
118 1.1 kardel timestamp_t tstamp;
119 1.1 kardel };
120 1.1 kardel
121 1.1 kardel clockformat_t clock_varitext =
122 1.1 kardel {
123 1.1 kardel inp_varitext, /* Because of the strange format we need to parse it ourselves */
124 1.1 kardel cvt_varitext, /* Varitext conversion */
125 1.1 kardel 0, /* no PPS monitoring */
126 1.1 kardel (void *)&varitext_fmt, /* conversion configuration */
127 1.1 kardel "Varitext Radio Clock", /* Varitext Radio Clock */
128 1.1 kardel 30, /* string buffer */
129 1.1 kardel sizeof(struct varitext), /* Private data size required to hold current parse state */
130 1.1 kardel };
131 1.1 kardel
132 1.1 kardel /*
133 1.3 christos * parse_cvt_fnc_t cvt_varitext
134 1.3 christos *
135 1.1 kardel * convert simple type format
136 1.1 kardel */
137 1.3 christos static u_long
138 1.1 kardel cvt_varitext(
139 1.1 kardel unsigned char *buffer,
140 1.1 kardel int size,
141 1.1 kardel struct format *format,
142 1.1 kardel clocktime_t *clock_time,
143 1.1 kardel void *local
144 1.1 kardel )
145 1.1 kardel {
146 1.1 kardel
147 1.3 christos if (!Strok(buffer, format->fixed_string)) {
148 1.1 kardel return CVT_NONE;
149 1.1 kardel } else {
150 1.1 kardel if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day,
151 1.1 kardel format->field_offsets[O_DAY].length) ||
152 1.1 kardel Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month,
153 1.1 kardel format->field_offsets[O_MONTH].length) ||
154 1.1 kardel Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year,
155 1.1 kardel format->field_offsets[O_YEAR].length) ||
156 1.1 kardel Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour,
157 1.1 kardel format->field_offsets[O_HOUR].length) ||
158 1.1 kardel Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute,
159 1.1 kardel format->field_offsets[O_MIN].length) ||
160 1.1 kardel Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second,
161 1.3 christos format->field_offsets[O_SEC].length)) {
162 1.1 kardel return CVT_FAIL | CVT_BADFMT;
163 1.1 kardel } else {
164 1.1 kardel u_char *f = (u_char*) &buffer[format->field_offsets[O_FLAGS].offset];
165 1.1 kardel
166 1.1 kardel clock_time->flags = 0;
167 1.1 kardel clock_time->utcoffset = 0;
168 1.1 kardel
169 1.1 kardel if (((*f) & VT_BST)) /* BST flag is set so set to indicate daylight saving time is active and utc offset */
170 1.1 kardel {
171 1.1 kardel clock_time->utcoffset = -1*60*60;
172 1.1 kardel clock_time->flags |= PARSEB_DST;
173 1.1 kardel }
174 1.1 kardel /*
175 1.3 christos if (!((*f) & VT_INITIALISED)) Clock not initialised
176 1.1 kardel clock_time->flags |= PARSEB_POWERUP;
177 1.3 christos
178 1.3 christos if (!((*f) & VT_SYNCHRONISED)) Clock not synchronised
179 1.1 kardel clock_time->flags |= PARSEB_NOSYNC;
180 1.3 christos
181 1.3 christos if (((*f) & VT_SEASON_CHANGE)) Seasonal change expected in the next hour
182 1.1 kardel clock_time->flags |= PARSEB_ANNOUNCE;
183 1.1 kardel */
184 1.3 christos return CVT_OK;
185 1.1 kardel }
186 1.1 kardel }
187 1.1 kardel }
188 1.1 kardel
189 1.3 christos /* parse_inp_fnc_t inp_varitext */
190 1.3 christos static u_long
191 1.1 kardel inp_varitext(
192 1.1 kardel parse_t *parseio,
193 1.3 christos char ch,
194 1.1 kardel timestamp_t *tstamp
195 1.1 kardel )
196 1.1 kardel {
197 1.1 kardel struct varitext *t = (struct varitext *)parseio->parse_pdata;
198 1.1 kardel int rtc;
199 1.1 kardel
200 1.5 christos parseprintf(DD_PARSE, ("inp_varitext(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
201 1.1 kardel
202 1.3 christos if (!t)
203 1.1 kardel return PARSE_INP_SKIP; /* local data not allocated - sigh! */
204 1.1 kardel
205 1.3 christos if (ch == 'T')
206 1.1 kardel t->tstamp = *tstamp;
207 1.1 kardel
208 1.1 kardel if ((t->previous_ch == 'T') && (ch == ':'))
209 1.1 kardel {
210 1.1 kardel parseprintf(DD_PARSE, ("inp_varitext: START seen\n"));
211 1.1 kardel
212 1.1 kardel parseio->parse_data[0] = 'T';
213 1.1 kardel parseio->parse_index=1;
214 1.1 kardel parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */
215 1.1 kardel t->start_found = 1;
216 1.1 kardel t->end_found = 0;
217 1.1 kardel t->end_count = 0;
218 1.1 kardel }
219 1.1 kardel
220 1.1 kardel if (t->start_found)
221 1.1 kardel {
222 1.1 kardel if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP)
223 1.1 kardel {
224 1.1 kardel parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n"));
225 1.1 kardel
226 1.1 kardel memset(t, 0, sizeof(struct varitext));
227 1.1 kardel return rtc;
228 1.1 kardel }
229 1.1 kardel
230 1.3 christos if (t->end_found)
231 1.1 kardel {
232 1.1 kardel if (++(t->end_count) == 4) /* Finally found the end of the message */
233 1.1 kardel {
234 1.1 kardel parseprintf(DD_PARSE, ("inp_varitext: END seen\n"));
235 1.1 kardel
236 1.1 kardel memset(t, 0, sizeof(struct varitext));
237 1.1 kardel if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP)
238 1.1 kardel return parse_end(parseio);
239 1.1 kardel else
240 1.1 kardel return rtc;
241 1.3 christos }
242 1.1 kardel }
243 1.1 kardel
244 1.3 christos if ((t->previous_ch == '\r') && (ch == '\n'))
245 1.1 kardel {
246 1.1 kardel t->end_found = 1;
247 1.1 kardel }
248 1.1 kardel
249 1.1 kardel }
250 1.3 christos
251 1.1 kardel t->previous_ch = ch;
252 1.1 kardel
253 1.1 kardel return PARSE_INP_SKIP;
254 1.1 kardel }
255 1.1 kardel
256 1.1 kardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */
257 1.1 kardel int clk_varitext_bs;
258 1.1 kardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */
259 1.1 kardel
260 1.1 kardel /*
261 1.1 kardel * History:
262 1.1 kardel *
263 1.1 kardel * clk_varitext.c,v
264 1.1 kardel * Revision 1.5 2005/04/16 17:32:10 kardel
265 1.1 kardel * update copyright
266 1.1 kardel *
267 1.1 kardel * Revision 1.4 2004/11/14 15:29:41 kardel
268 1.1 kardel * support PPSAPI, upgrade Copyright to Berkeley style
269 1.1 kardel *
270 1.1 kardel *
271 1.1 kardel * Revision 1.0 1997/06/02 13:16:30 McConnell
272 1.1 kardel * File created
273 1.1 kardel *
274 1.1 kardel */
275