1 = How to build new GENERIC clocks
2 include::include-html.ad[]
4 Here is an attempt to sketch out what you need to do to add
5 another clock to the generic driver: Currently the implementation is being
6 cleaned up - so not all information in here is completely correct. Refer
7 to the included code where in doubt.
11 * Does the system you want the clock connect to have the include file
12 termios.h? (You need that for the generic driver)
16 Make a conversion module (libparse/clk_*.c)
18 == What is the time code format?
20 Find year, month, day, hour, minute, second, status (synchronised or
21 not), possibly time zone information (you need to give the offset to
22 UTC) You will have to convert the data from a string into a struct
25 -------------------------------------------------------------------------------
26 struct clocktime /* clock time broken up from time code */
35 long utcoffset; /* in seconds */
36 time_t utcoffset; /* true utc time instead of date/time */
37 long flags; /* current clock status */
39 -------------------------------------------------------------------------------
41 Conversion is usually simple and straightforward. For the flags
42 following values can be OR'ed together:
44 |-------------------------------------------------------------------------------
45 | PARSEB_ANNOUNCE | Switch time zone warning (informational only)
46 | PARSEB_POWERUP | No synchronisation - clock confused (must set then)
47 | PARSEB_NOSYNC | Timecode currently not confirmed (must set then),
48 usually on reception error when there is still a
49 chance the generated time is still ok.
50 | PARSEB_DST | DST in effect (informational only)
51 | PARSEB_UTC | Timecode contains UTC time (informational only)
52 | PARSEB_LEAPADD | LEAP addition warning (prior to leap happening -
53 must set when imminent)
54 Also used for time code that do not encode the
55 direction (as this is currently the default).
56 | PARSEB_LEAPDEL | LEAP deletion warning (prior to leap happening -
57 must set when imminent)
58 | PARSEB_ALTERNATE | Backup transmitter (informational only)
59 | PARSEB_POSITION | Geographic position available (informational only)
60 | PARSEB_LEAPSECOND| Actual leap second (this time code is the leap
61 second - informational only)
62 |-------------------------------------------------------------------------------
64 These are feature flags denoting items that are supported by the clock:
66 |----------------------------------------------------------------------------
67 | PARSEB_S_LEAP | supports LEAP - might set PARSEB_LEAP
68 | PARSEB_S_ANTENNA | supports ANTENNA - might set PARSEB_ALTERNATE
69 | PARSEB_S_PPS | supports PPS time stamping
70 | PARSEB_S_POSITION | supports position information (GPS)
71 |----------------------------------------------------------------------------
73 If the utctime field is non-zero this value will be take as time code
74 value. This allows for conversion routines that already have the utc
75 time value. The utctime field gives the seconds since Jan 1st 1970,
76 0:00:00. The useconds field gives the respective usec value. The fields
77 for date and time (down to second resolution) will be ignored.
79 Conversion is done in the cvt_* routine in parse/clk_*.c files. Look in
80 them for examples. The basic structure is:
82 -----------------------------------------------------
83 struct clockformat <yourclock>_format = {
84 lots of fields for you to fill out (see below)
87 static cvt_<yourclock>()
90 if (<I do not recognize my time code>) {
93 if (<conversion into clockformat is ok>) {
94 <set all necessary flags>;
97 return CVT_FAIL|CVT_BADFMT;
100 -----------------------------------------------------
102 The struct clockformat is the interface to the rest of the generic
103 driver - it holds all information necessary for finding the clock
104 message and doing the appropriate time stamping.
106 --------------------------------------------------------------------------------
109 unsigned long (*input)();
110 /* input routine - your routine - cvt_<yourclock> */
111 unsigned long (*convert)();
112 /* conversion routine - your routine - cvt_<yourclock> */
113 /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
114 unsigned long (*syncpps)();
115 /* PPS input routine - usually pps_one */
117 /* local parameters - any parameters/data/configuration info your conversion
118 routine might need */
120 /* clock format name - Name of the time code */
121 unsigned short length;
122 /* maximum length of data packet for your clock format */
124 /* information for the parser what to look for */
126 --------------------------------------------------------------------------------
128 The above should have given you some hints on how to build a clk_*.c
129 file with the time code conversion. See the examples and pick a clock
130 closest to yours and tweak the code to match your clock.
132 In order to make your clk_*.c file usable, a reference to the clockformat
133 structure must be put into parse_conf.c.
135 == Driver initialization
137 TTY setup and initialization/configuration will be done in
138 ntpd/refclock_generic.c.
140 * Find out the exact tty settings for your clock (baud rate, parity,
141 stop bits, character size, ...) and note them in terms of termio*.h
144 * in ntpd/refclock_generic.c fill out a new the struct clockinfo element
145 (that allocates a new "IP" address - see comments) (see all the other
148 --------------------------------------------------------------------------------
150 unsigned long cl_flags; /* operation flags (io modes) */
151 PARSE_F_PPSPPS use loopfilter PPS code
152 PARSE_F_PPSONSECOND PPS pulses are on second
153 usually flags stay 0 as they are used only for special setups
155 void (*cl_poll)(); /* active poll routine */
156 The routine to call when the clock needs data sent to it in order to
157 get a time code from the clock (e.g., Trimble clock)
159 int (*cl_init)(); /* active poll init routine */
160 The routine to call for very special initializations.
162 void (*cl_event)(); /* special event handling (e.g., reset clock) */
163 What to do, when an event happens - used to re-initialize clocks on timeout.
165 void (*cl_end)(); /* active poll end routine */
166 The routine to call to undo any special initialization (free memory/timers)
168 void *cl_data; /* local data area for "poll" mechanism */
169 local data for polling routines
171 u_fp cl_rootdelay; /* rootdelay */
172 NTP rootdelay estimate (usually 0)
174 unsigned long cl_basedelay; /* current offset - unsigned l_fp
175 fractional part (fraction) by
176 which the RS232 time code is
177 delayed from the actual time. */
179 unsigned long cl_ppsdelay; /* current PPS offset - unsigned
180 l_fp fractional time (fraction)
181 by which the PPS time stamp is
182 delayed (usually 0) */
184 char *cl_id; /* ID code */
185 Refclock id - (max 4 chars)
187 char *cl_description; /* device name */
190 char *cl_format; /* fixed format */
191 If the data format can not be detected automatically this is the name
192 as in clk_*.c clockformat.
194 unsigned char cl_type; /* clock type (ntp control) */
195 Type if clock as in clock status word (ntp control messages) - usually 0
197 unsigned long cl_maxunsync; /* time to trust oscillator after
198 losing synch -- seconds a clock
199 can be trusted after losing
201 unsigned long cl_speed; /* terminal input & output baudrate */
202 unsigned long cl_cflag; /* terminal io flags */
203 unsigned long cl_iflag; /* terminal io flags */
204 unsigned long cl_oflag; /* terminal io flags */
205 unsigned long cl_lflag; /* terminal io flags */
207 unsigned long cl_samples; /* samples for median filter */
208 unsigned long cl_keep; /* samples for median filter to keep */
209 median filter parameters - smoothing and rejection of bad samples
211 ...,<other clocks>,...
212 { < your parameters> },
214 --------------------------------------------------------------------------------
216 Well, this is very sketchy, I know. But I hope it helps a little bit.
217 The best way is to look which clock comes closest to yours and tweak that
220 Two sorts of clocks are used with parse. Clocks that automatically send
221 their time code (once a second) do not need entries in the poll routines
222 because they send the data all the time. The second sort are the clocks
223 that need a command sent to them in order to reply with a time code
224 (like the Trimble clock).
226 For questions: mailto:kardel@acm.org[kardel@acm.org].
228 Please include an exact description on how your clock works.
229 (initialization, TTY modes, strings to be sent to it, responses received
234 include::includes/footer.adoc[]