summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/html/parsenew.htm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/html/parsenew.htm')
-rw-r--r--contrib/ntp/html/parsenew.htm237
1 files changed, 237 insertions, 0 deletions
diff --git a/contrib/ntp/html/parsenew.htm b/contrib/ntp/html/parsenew.htm
new file mode 100644
index 0000000..0ef60bc
--- /dev/null
+++ b/contrib/ntp/html/parsenew.htm
@@ -0,0 +1,237 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML Strict//EN">
+<TITLE>Making PARSE Clocks</TITLE>
+<h1>How to build new PARSE clocks</h1>
+
+<p>Here is an attempt to sketch out what you need to do in order to
+add another clock to the parse driver:
+Currently the implementation is being cleaned up - so not all information
+in here is completely correct. Refer to the included code where in doubt.
+
+
+<p>Prerequisites:
+<ul>
+<li>Does the system you want the clock connect to have the include files
+termio.h or termios.h ? (You need that for the parse driver)
+</ul>
+
+
+<p>What to do:
+
+
+<p>Make a conversion module (libparse/clk_*.c)
+
+<ol>
+<li>What ist the time code format ?
+<ul>
+<li> find year, month, day, hour, minute, second, status (synchronised or
+not), possibly time zone information (you need to give the offset to UTC)
+You will have to convert the data from a string into a struct clocktime:
+<pre>
+ struct clocktime /* clock time broken up from time code */
+ {
+ long day;
+ long month;
+ long year;
+ long hour;
+ long minute;
+ long second;
+ long usecond;
+ long utcoffset; /* in seconds */
+ time_t utcoffset; /* true utc time instead of date/time */
+ long flags; /* current clock status */
+ };
+</pre>
+
+<p>Conversion is usually simple and straight forward. For the flags following
+values can be OR'ed together:
+<PRE>
+ PARSEB_ANNOUNCE switch time zone warning (informational only)
+ PARSEB_POWERUP no synchronisation - clock confused (must set then)
+ PARSEB_NOSYNC timecode currently not confirmed (must set then)
+ usually on reception error when there is still a
+ chance the the generated time is still ok.
+
+ PARSEB_DST DST in effect (informational only)
+ PARSEB_UTC timecode contains UTC time (informational only)
+ PARSEB_LEAPADD LEAP addition warning (prior to leap happening - must set when imminent)
+ also used for time code that do not encode the
+ direction (as this is currently the default).
+ PARSEB_LEAPDEL LEAP deletion warning (prior to leap happening - must set when imminent)
+ PARSEB_ALTERNATE backup transmitter (informational only)
+ PARSEB_POSITION geographic position available (informational only)
+ PARSEB_LEAPSECOND actual leap second (this time code is the leap
+ second - informational only)
+</PRE>
+
+<p>These are feature flags denoting items that are supported by the clock:
+ <PRE>
+ PARSEB_S_LEAP supports LEAP - might set PARSEB_LEAP
+ PARSEB_S_ANTENNA supports ANTENNA - might set PARSEB_ALTERNATE
+ PARSEB_S_PPS supports PPS time stamping
+ PARSEB_S_POSITION supports position information (GPS)
+ </PRE>
+
+ <p>If the utctime field is non zero this value will be take as
+ time code value. This allows for conversion routines that
+ already have the utc time value. The utctime field gives the seconds
+ since Jan 1st 1970, 0:00:00. The useconds field gives the respective
+ usec value. The fields for date and time (down to second resolution)
+ will be ignored.
+
+
+ <p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in
+ them for examples. The basic structure is:
+
+<PRE>
+ struct clockformat &lt;yourclock&gt;_format = {
+ lots of fields for you to fill out (see below)
+ };
+
+ static cvt_&lt;yourclock&gt;()
+ ...
+ {
+ if (&lt;I do not recognize my time code&gt;) {
+ return CVT_NONE;
+ } else {
+ if (&lt;conversion into clockformat is ok&gt;) {
+ &lt;set all necessary flags&gt;;
+ return CVT_OK;
+ } else {
+ return CVT_FAIL|CVT_BADFMT;
+ }
+ }
+</PRE>
+
+
+<p>The struct clockformat is the interface to the rest of the parse
+ driver - it holds all information necessary for finding the
+ clock message and doing the appropriate time stamping.
+
+<PRE>
+struct clockformat
+{
+ u_long (*input)();
+ /* input routine - your routine - cvt_&lt;yourclock&gt; */
+ u_long (*convert)();
+ /* conversion routine - your routine - cvt_&lt;yourclock&gt; */
+ /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
+ u_long (*syncpps)();
+ /* PPS input routine - usually pps_one */
+ void *data;
+ /* local parameters - any parameters/data/configuration info your conversion
+ routine might need */
+ char *name;
+ /* clock format name - Name of the time code */
+ unsigned short length;
+ /* maximum length of data packet for your clock format */
+ u_long flags;
+ /* information for the parser what to look for */
+};
+</PRE>
+
+
+<p>The above should have given you some hints on how to build a clk_*.c
+ file with the time code conversion. See the examples and pick a clock
+ closest to yours and tweak the code to match your clock.
+
+
+ <p>In order to make your clk_*.c file usable a reference to the clockformat
+ structure must be put into parse_conf.c.
+</ul>
+<li>TTY setup and initialisation/configuration will be done in
+ntpd/refclock_parse.c.
+<ul>
+<li>Find out the exact tty settings for your clock (baud rate, parity,
+stop bits, character size, ...) and note them in terms of
+termio*.h c_cflag macros.
+<li>in ntpd/refclock_parse.c fill out a new the struct clockinfo element
+(that allocates a new "IP" address - see comments)
+(see all the other clocks for example)
+<PRE>
+ struct clockinfo
+ {
+ u_long cl_flags; /* operation flags (io modes) */
+ PARSE_F_PPSPPS use loopfilter PPS code (CIOGETEV)
+ PARSE_F_PPSONSECOND PPS pulses are on second
+ usually flags stay 0 as they are used only for special setups
+
+ void (*cl_poll)(); /* active poll routine */
+ The routine to call when the clock needs data sent to it in order to
+ get a time code from the clock (e.g. Trimble clock)
+
+ int (*cl_init)(); /* active poll init routine */
+ The routine to call for very special initializations.
+
+ void (*cl_event)(); /* special event handling (e.g. reset clock) */
+ What to do, when an event happens - used to re-initialize clocks on timeout.
+
+ void (*cl_end)(); /* active poll end routine */
+ The routine to call to undo any special initialisation (free memory/timers)
+
+ void *cl_data; /* local data area for "poll" mechanism */
+ local data for polling routines
+
+ u_fp cl_rootdelay; /* rootdelay */
+ NTP rootdelay estimate (usually 0)
+
+ u_long cl_basedelay; /* current offset - unsigned l_fp
+ fractional part (fraction) by
+ which the RS232 time code is
+ delayed from the actual time. */
+
+ u_long cl_ppsdelay; /* current PPS offset - unsigned l_fp fractional
+ time (fraction) by which the PPS time stamp is delayed (usually 0)
+ part */
+
+ char *cl_id; /* ID code (usually "DCF") */
+ Refclock id - (max 4 chars)
+
+ char *cl_description; /* device name */
+ Name of this device.
+
+ char *cl_format; /* fixed format */
+ If the data format cann not ne detected automatically this is the name
+ as in clk_*.c clockformat.
+
+ u_char cl_type; /* clock type (ntp control) */
+ Type if clock as in clock status word (ntp control messages) - usually 0
+
+ u_long cl_maxunsync; /* time to trust oscillator after loosing synch
+ */
+ seconds a clock can be trusted after loosing synchronisation.
+
+ u_long cl_speed; /* terminal input & output baudrate */
+ u_long cl_cflag; /* terminal io flags */
+ u_long cl_iflag; /* terminal io flags */
+ u_long cl_oflag; /* terminal io flags */
+ u_long cl_lflag; /* terminal io flags */
+ termio*.h tty modes.
+
+ u_long cl_samples; /* samples for median filter */
+ u_long cl_keep; /* samples for median filter to keep */
+ median filter parameters - smoothing and rejection of bad samples
+ } clockinfo[] = {
+ ...,&lt;other clocks&gt;,...
+ { &lt; your parameters&gt; },
+ };
+
+</PRE>
+</ul>
+</ol>
+
+<p>Well, this is very sketchy, i know. But I hope it helps a little bit.
+The best way is to look which clock comes closest to your and tweak that
+code.
+
+<p>Two sorts of clocks are used with parse. Clocks that automatically send
+their time code (once a second) do not need entries in the poll routines because
+they send the data all the time. The second sort are the clocks that need a
+command sent to them in order to reply with a time code (like the Trimble
+clock).
+
+<p>For questions: <a href="mailto: kardel@acm.org">kardel@acm.org</a>.
+
+<p>Please include an exact description on how your clock works. (initialisation,
+TTY modes, strings to be sent to it, responses received from the clock).
+<hr><p>
+<a href="http://www4.informatik.uni-erlangen.de/~kardel">Frank Kardel</a>
OpenPOWER on IntegriCloud