Change the default for ntpd back to -s, the bug which triggered this
[dragonfly.git] / contrib / ntp / html / parsenew.htm
1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML Strict//EN">
2 <TITLE>Making PARSE Clocks</TITLE>
3 <h1>How to build new PARSE clocks</h1>
4
5 <p>Here is an attempt to sketch out what you need to do in order to
6 add another clock to the parse driver:
7 Currently the implementation is being cleaned up - so not all information
8 in here is completely correct. Refer to the included code where in doubt.
9
10
11 <p>Prerequisites:
12 <ul>
13 <li>Does the system you want the clock connect to have the include files
14 termio.h or termios.h ? (You need that for the parse driver)
15 </ul>
16
17
18 <p>What to do:
19
20
21 <p>Make a conversion module (libparse/clk_*.c)
22
23 <ol>
24 <li>What ist the time code format ?
25 <ul>
26 <li> find year, month, day, hour, minute, second, status (synchronised or
27 not), possibly time zone information (you need to give the offset to UTC)
28 You will have to convert the data from a string into a struct clocktime:
29 <pre>
30       struct clocktime                /* clock time broken up from time code */
31       {
32         long day;
33         long month;
34         long year;
35         long hour;
36         long minute;
37         long second;
38         long usecond;
39         long utcoffset;       /* in seconds */
40         time_t utcoffset;     /* true utc time instead of date/time */
41         long flags;           /* current clock status */
42       };
43 </pre>
44
45 <p>Conversion is usually simple and straight forward. For the flags following
46 values can be OR'ed together:
47 <PRE>
48      PARSEB_ANNOUNCE           switch time zone warning (informational only)
49      PARSEB_POWERUP            no synchronisation - clock confused (must set then)
50      PARSEB_NOSYNC             timecode currently not confirmed (must set then)
51                                usually on reception error when there is still a
52                                chance the the generated time is still ok.
53
54      PARSEB_DST                DST in effect (informational only)
55      PARSEB_UTC                timecode contains UTC time (informational only)
56      PARSEB_LEAPADD            LEAP addition warning (prior to leap happening - must set when imminent)
57                                also used for time code that do not encode the
58                                direction (as this is currently the default).
59      PARSEB_LEAPDEL            LEAP deletion warning (prior to leap happening - must set when imminent)
60      PARSEB_ALTERNATE          backup transmitter (informational only)
61      PARSEB_POSITION           geographic position available (informational only)
62      PARSEB_LEAPSECOND         actual leap second (this time code is the leap
63                                second - informational only)
64 </PRE>
65
66 <p>These are feature flags denoting items that are supported by the clock:
67    <PRE>
68      PARSEB_S_LEAP             supports LEAP - might set PARSEB_LEAP
69      PARSEB_S_ANTENNA          supports ANTENNA - might set PARSEB_ALTERNATE
70      PARSEB_S_PPS              supports PPS time stamping
71      PARSEB_S_POSITION         supports position information (GPS)
72    </PRE>
73
74    <p>If the utctime field is non zero this value will be take as
75      time code value. This allows for conversion routines that
76      already have the utc time value. The utctime field gives the seconds
77      since Jan 1st 1970, 0:00:00. The useconds field gives the respective
78      usec value. The fields for date and time (down to second resolution)
79      will be ignored.
80
81
82      <p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in
83      them for examples. The basic structure is:
84
85 <PRE>
86      struct clockformat &lt;yourclock&gt;_format = {
87        lots of fields for you to fill out (see below)
88      };
89
90      static cvt_&lt;yourclock&gt;()
91        ...
92      {
93        if (&lt;I do not recognize my time code&gt;) {
94          return CVT_NONE;
95        } else {
96          if (&lt;conversion into clockformat is ok&gt;) {
97            &lt;set all necessary flags&gt;;
98            return CVT_OK;
99          } else {
100            return CVT_FAIL|CVT_BADFMT;
101          }
102        }
103 </PRE>
104
105
106 <p>The struct clockformat is the interface to the rest of the parse
107      driver - it holds all information necessary for finding the
108      clock message and doing the appropriate time stamping.
109
110 <PRE>
111 struct clockformat
112 {
113   u_long (*input)();
114   /* input routine - your routine - cvt_&lt;yourclock&gt; */
115   u_long (*convert)();
116   /* conversion routine - your routine - cvt_&lt;yourclock&gt; */
117   /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
118   u_long (*syncpps)(); 
119   /* PPS input routine - usually pps_one */
120   void           *data;
121   /* local parameters - any parameters/data/configuration info your conversion
122      routine might need */
123   char           *name;
124   /* clock format name - Name of the time code */
125   unsigned short  length;
126   /* maximum length of data packet for your clock format */
127   u_long   flags;
128  /* information for the parser what to look for */
129 };
130 </PRE>
131
132
133 <p>The above should have given you some hints on how to build a clk_*.c
134   file with the time code conversion. See the examples and pick a clock
135   closest to yours and tweak the code to match your clock.
136
137
138   <p>In order to make your clk_*.c file usable a reference to the clockformat
139   structure must be put into parse_conf.c.
140 </ul>
141 <li>TTY setup and initialisation/configuration will be done in
142 ntpd/refclock_parse.c.
143 <ul>
144 <li>Find out the exact tty settings for your clock (baud rate, parity,
145 stop bits, character size, ...) and note them in terms of
146 termio*.h c_cflag macros.
147 <li>in ntpd/refclock_parse.c fill out a new the struct clockinfo element
148 (that allocates a new "IP" address - see comments)
149 (see all the other clocks for example)
150 <PRE>
151    struct clockinfo
152      {
153       u_long  cl_flags;             /* operation flags (io modes) */
154          PARSE_F_PPSPPS       use loopfilter PPS code (CIOGETEV)
155          PARSE_F_PPSONSECOND  PPS pulses are on second
156          usually flags stay 0 as they are used only for special setups
157
158     void  (*cl_poll)();           /* active poll routine */
159          The routine to call when the clock needs data sent to it in order to
160          get a time code from the clock (e.g. Trimble clock)
161
162     int   (*cl_init)();           /* active poll init routine */
163          The routine to call for very special initializations.
164
165     void  (*cl_event)();          /* special event handling (e.g. reset clock) */
166          What to do, when an event happens - used to re-initialize clocks on timeout.
167
168     void  (*cl_end)();            /* active poll end routine */
169          The routine to call to undo any special initialisation (free memory/timers)
170
171     void   *cl_data;              /* local data area for "poll" mechanism */
172          local data for polling routines
173
174     u_fp    cl_rootdelay;         /* rootdelay */
175          NTP rootdelay estimate (usually 0)
176
177              u_long  cl_basedelay;         /* current offset - unsigned l_fp
178                                               fractional part (fraction) by
179                                               which the RS232 time code is
180                                               delayed from the actual time. */
181
182     u_long  cl_ppsdelay;          /* current PPS offset - unsigned l_fp fractional
183          time (fraction) by which the PPS time stamp is delayed (usually 0)
184    part */
185
186     char   *cl_id;                /* ID code (usually "DCF") */
187          Refclock id - (max 4 chars)
188
189     char   *cl_description;       /* device name */
190          Name of this device.
191
192     char   *cl_format;            /* fixed format */
193          If the data format cann not ne detected automatically this is the name
194          as in clk_*.c clockformat.
195
196     u_char  cl_type;              /* clock type (ntp control) */
197          Type if clock as in clock status word (ntp control messages) - usually 0
198          
199     u_long  cl_maxunsync;         /* time to trust oscillator after loosing synch
200   */
201          seconds a clock can be trusted after loosing synchronisation.
202
203     u_long  cl_speed;             /* terminal input & output baudrate */
204     u_long  cl_cflag;             /* terminal io flags */
205     u_long  cl_iflag;             /* terminal io flags */
206     u_long  cl_oflag;             /* terminal io flags */
207     u_long  cl_lflag;             /* terminal io flags */
208          termio*.h tty modes.
209
210     u_long  cl_samples;           /* samples for median filter */
211     u_long  cl_keep;              /* samples for median filter to keep */
212          median filter parameters - smoothing and rejection of bad samples
213   } clockinfo[] = {
214   ...,&lt;other clocks&gt;,...
215   { &lt; your parameters&gt; },
216   };
217
218 </PRE>
219 </ul>
220 </ol>
221
222 <p>Well, this is very sketchy, i know. But I hope it helps a little bit.
223 The best way is to look which clock comes closest to your and tweak that
224 code.
225
226 <p>Two sorts of clocks are used with parse. Clocks that automatically send
227 their time code (once a second) do not need entries in the poll routines because
228 they send the data all the time. The second sort are the clocks that need a
229 command sent to them in order to reply with a time code (like the Trimble
230 clock).
231
232 <p>For questions: <a href="mailto: kardel@acm.org">kardel@acm.org</a>.
233
234 <p>Please include an exact description on how your clock works. (initialisation,
235 TTY modes, strings to be sent to it, responses received from the clock).
236 <hr><p>
237 <a href="http://www4.informatik.uni-erlangen.de/~kardel">Frank Kardel</a>