xref: /freebsd/contrib/ntp/html/parsenew.html (revision ea906c4152774dff300bb26fbfc1e4188351c89a)
19c2daa00SOllivier Robert<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
29c2daa00SOllivier Robert
39c2daa00SOllivier Robert<html>
49c2daa00SOllivier Robert
59c2daa00SOllivier Robert	<head>
6ea906c41SOllivier Robert		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
79c2daa00SOllivier Robert		<title>Making PARSE Clocks</title>
89c2daa00SOllivier Robert		<link href="scripts/style.css" type="text/css" rel="stylesheet">
99c2daa00SOllivier Robert	</head>
109c2daa00SOllivier Robert
119c2daa00SOllivier Robert	<body>
129c2daa00SOllivier Robert		<h3>How to build new PARSE clocks</h3>
139c2daa00SOllivier Robert		<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>
149c2daa00SOllivier Robert		<p>Prerequisites:</p>
159c2daa00SOllivier Robert		<ul>
169c2daa00SOllivier Robert			<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)
179c2daa00SOllivier Robert		</ul>
189c2daa00SOllivier Robert		<p>What to do:</p>
199c2daa00SOllivier Robert		<p>Make a conversion module (libparse/clk_*.c)</p>
209c2daa00SOllivier Robert		<ol>
219c2daa00SOllivier Robert			<li>What ist the time code format ?
229c2daa00SOllivier Robert				<ul>
239c2daa00SOllivier Robert					<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:
249c2daa00SOllivier Robert						<pre>
259c2daa00SOllivier Robert      struct clocktime                /* clock time broken up from time code */
269c2daa00SOllivier Robert      {
279c2daa00SOllivier Robert	long day;
289c2daa00SOllivier Robert	long month;
299c2daa00SOllivier Robert	long year;
309c2daa00SOllivier Robert	long hour;
319c2daa00SOllivier Robert	long minute;
329c2daa00SOllivier Robert	long second;
339c2daa00SOllivier Robert	long usecond;
349c2daa00SOllivier Robert	long utcoffset;       /* in seconds */
359c2daa00SOllivier Robert	time_t utcoffset;     /* true utc time instead of date/time */
369c2daa00SOllivier Robert	long flags;           /* current clock status */
379c2daa00SOllivier Robert      };
389c2daa00SOllivier Robert</pre>
399c2daa00SOllivier Robert						<p>Conversion is usually simple and straight forward. For the flags following values can be OR'ed together:</p>
409c2daa00SOllivier Robert						<pre>
419c2daa00SOllivier Robert     PARSEB_ANNOUNCE           switch time zone warning (informational only)
429c2daa00SOllivier Robert     PARSEB_POWERUP            no synchronisation - clock confused (must set then)
439c2daa00SOllivier Robert     PARSEB_NOSYNC             timecode currently not confirmed (must set then)
449c2daa00SOllivier Robert                               usually on reception error when there is still a
459c2daa00SOllivier Robert                               chance the the generated time is still ok.
469c2daa00SOllivier Robert
479c2daa00SOllivier Robert     PARSEB_DST                DST in effect (informational only)
489c2daa00SOllivier Robert     PARSEB_UTC                timecode contains UTC time (informational only)
499c2daa00SOllivier Robert     PARSEB_LEAPADD            LEAP addition warning (prior to leap happening - must set when imminent)
509c2daa00SOllivier Robert			       also used for time code that do not encode the
519c2daa00SOllivier Robert			       direction (as this is currently the default).
529c2daa00SOllivier Robert     PARSEB_LEAPDEL            LEAP deletion warning (prior to leap happening - must set when imminent)
539c2daa00SOllivier Robert     PARSEB_ALTERNATE          backup transmitter (informational only)
549c2daa00SOllivier Robert     PARSEB_POSITION           geographic position available (informational only)
559c2daa00SOllivier Robert     PARSEB_LEAPSECOND         actual leap second (this time code is the leap
569c2daa00SOllivier Robert                               second - informational only)
579c2daa00SOllivier Robert</pre>
589c2daa00SOllivier Robert						<p>These are feature flags denoting items that are supported by the clock:</p>
599c2daa00SOllivier Robert						<pre>
609c2daa00SOllivier Robert     PARSEB_S_LEAP             supports LEAP - might set PARSEB_LEAP
619c2daa00SOllivier Robert     PARSEB_S_ANTENNA          supports ANTENNA - might set PARSEB_ALTERNATE
629c2daa00SOllivier Robert     PARSEB_S_PPS              supports PPS time stamping
639c2daa00SOllivier Robert     PARSEB_S_POSITION         supports position information (GPS)
649c2daa00SOllivier Robert   </pre>
659c2daa00SOllivier Robert						<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>
669c2daa00SOllivier Robert						<p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in them for examples. The basic structure is:</p>
679c2daa00SOllivier Robert						<pre>
689c2daa00SOllivier Robert     struct clockformat &lt;yourclock&gt;_format = {
699c2daa00SOllivier Robert       lots of fields for you to fill out (see below)
709c2daa00SOllivier Robert     };
719c2daa00SOllivier Robert
729c2daa00SOllivier Robert     static cvt_&lt;yourclock&gt;()
739c2daa00SOllivier Robert       ...
749c2daa00SOllivier Robert     {
759c2daa00SOllivier Robert       if (&lt;I do not recognize my time code&gt;) {
769c2daa00SOllivier Robert         return CVT_NONE;
779c2daa00SOllivier Robert       } else {
789c2daa00SOllivier Robert         if (&lt;conversion into clockformat is ok&gt;) {
799c2daa00SOllivier Robert           &lt;set all necessary flags&gt;;
809c2daa00SOllivier Robert           return CVT_OK;
819c2daa00SOllivier Robert         } else {
829c2daa00SOllivier Robert           return CVT_FAIL|CVT_BADFMT;
839c2daa00SOllivier Robert         }
849c2daa00SOllivier Robert       }
859c2daa00SOllivier Robert</pre>
869c2daa00SOllivier Robert						<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.</p>
879c2daa00SOllivier Robert						<pre>
889c2daa00SOllivier Robertstruct clockformat
899c2daa00SOllivier Robert{
909c2daa00SOllivier Robert  u_long (*input)();
919c2daa00SOllivier Robert  /* input routine - your routine - cvt_&lt;yourclock&gt; */
929c2daa00SOllivier Robert  u_long (*convert)();
939c2daa00SOllivier Robert  /* conversion routine - your routine - cvt_&lt;yourclock&gt; */
949c2daa00SOllivier Robert  /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
959c2daa00SOllivier Robert  u_long (*syncpps)();
969c2daa00SOllivier Robert  /* PPS input routine - usually pps_one */
979c2daa00SOllivier Robert  void           *data;
989c2daa00SOllivier Robert  /* local parameters - any parameters/data/configuration info your conversion
999c2daa00SOllivier Robert     routine might need */
1009c2daa00SOllivier Robert  char           *name;
1019c2daa00SOllivier Robert  /* clock format name - Name of the time code */
1029c2daa00SOllivier Robert  unsigned short  length;
1039c2daa00SOllivier Robert  /* maximum length of data packet for your clock format */
1049c2daa00SOllivier Robert  u_long   flags;
1059c2daa00SOllivier Robert /* information for the parser what to look for */
1069c2daa00SOllivier Robert};
1079c2daa00SOllivier Robert</pre>
1089c2daa00SOllivier Robert						<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>
1099c2daa00SOllivier Robert						<p>In order to make your clk_*.c file usable a reference to the clockformat structure must be put into parse_conf.c.</p>
1109c2daa00SOllivier Robert				</ul>
1119c2daa00SOllivier Robert			<li>TTY setup and initialisation/configuration will be done in ntpd/refclock_parse.c.
1129c2daa00SOllivier Robert				<ul>
1139c2daa00SOllivier Robert					<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.
1149c2daa00SOllivier Robert					<li>in ntpd/refclock_parse.c fill out a new the struct clockinfo element (that allocates a new &quot;IP&quot; address - see comments) (see all the other clocks for example)
1159c2daa00SOllivier Robert						<pre>
1169c2daa00SOllivier Robert   struct clockinfo
1179c2daa00SOllivier Robert     {
1189c2daa00SOllivier Robert      u_long  cl_flags;             /* operation flags (io modes) */
1199c2daa00SOllivier Robert	 PARSE_F_PPSPPS       use loopfilter PPS code (CIOGETEV)
1209c2daa00SOllivier Robert	 PARSE_F_PPSONSECOND  PPS pulses are on second
1219c2daa00SOllivier Robert	 usually flags stay 0 as they are used only for special setups
1229c2daa00SOllivier Robert
1239c2daa00SOllivier Robert    void  (*cl_poll)();           /* active poll routine */
1249c2daa00SOllivier Robert         The routine to call when the clock needs data sent to it in order to
1259c2daa00SOllivier Robert         get a time code from the clock (e.g. Trimble clock)
1269c2daa00SOllivier Robert
1279c2daa00SOllivier Robert    int   (*cl_init)();           /* active poll init routine */
1289c2daa00SOllivier Robert         The routine to call for very special initializations.
1299c2daa00SOllivier Robert
1309c2daa00SOllivier Robert    void  (*cl_event)();          /* special event handling (e.g. reset clock) */
1319c2daa00SOllivier Robert         What to do, when an event happens - used to re-initialize clocks on timeout.
1329c2daa00SOllivier Robert
1339c2daa00SOllivier Robert    void  (*cl_end)();            /* active poll end routine */
1349c2daa00SOllivier Robert         The routine to call to undo any special initialisation (free memory/timers)
1359c2daa00SOllivier Robert
1369c2daa00SOllivier Robert    void   *cl_data;              /* local data area for &quot;poll&quot; mechanism */
1379c2daa00SOllivier Robert         local data for polling routines
1389c2daa00SOllivier Robert
1399c2daa00SOllivier Robert    u_fp    cl_rootdelay;         /* rootdelay */
1409c2daa00SOllivier Robert         NTP rootdelay estimate (usually 0)
1419c2daa00SOllivier Robert
1429c2daa00SOllivier Robert	     u_long  cl_basedelay;         /* current offset - unsigned l_fp
1439c2daa00SOllivier Robert                                              fractional part (fraction) by
1449c2daa00SOllivier Robert                                              which the RS232 time code is
1459c2daa00SOllivier Robert                                              delayed from the actual time. */
1469c2daa00SOllivier Robert
1479c2daa00SOllivier Robert    u_long  cl_ppsdelay;          /* current PPS offset - unsigned l_fp fractional
1489c2daa00SOllivier Robert         time (fraction) by which the PPS time stamp is delayed (usually 0)
1499c2daa00SOllivier Robert   part */
1509c2daa00SOllivier Robert
1519c2daa00SOllivier Robert    char   *cl_id;                /* ID code (usually &quot;DCF&quot;) */
1529c2daa00SOllivier Robert         Refclock id - (max 4 chars)
1539c2daa00SOllivier Robert
1549c2daa00SOllivier Robert    char   *cl_description;       /* device name */
1559c2daa00SOllivier Robert         Name of this device.
1569c2daa00SOllivier Robert
1579c2daa00SOllivier Robert    char   *cl_format;            /* fixed format */
1589c2daa00SOllivier Robert         If the data format cann not ne detected automatically this is the name
1599c2daa00SOllivier Robert	 as in clk_*.c clockformat.
1609c2daa00SOllivier Robert
1619c2daa00SOllivier Robert    u_char  cl_type;              /* clock type (ntp control) */
1629c2daa00SOllivier Robert         Type if clock as in clock status word (ntp control messages) - usually 0
1639c2daa00SOllivier Robert
1649c2daa00SOllivier Robert    u_long  cl_maxunsync;         /* time to trust oscillator after losing synch
1659c2daa00SOllivier Robert  */
1669c2daa00SOllivier Robert         seconds a clock can be trusted after losing synchronisation.
1679c2daa00SOllivier Robert
1689c2daa00SOllivier Robert    u_long  cl_speed;             /* terminal input &amp; output baudrate */
1699c2daa00SOllivier Robert    u_long  cl_cflag;             /* terminal io flags */
1709c2daa00SOllivier Robert    u_long  cl_iflag;             /* terminal io flags */
1719c2daa00SOllivier Robert    u_long  cl_oflag;             /* terminal io flags */
1729c2daa00SOllivier Robert    u_long  cl_lflag;             /* terminal io flags */
1739c2daa00SOllivier Robert         termio*.h tty modes.
1749c2daa00SOllivier Robert
1759c2daa00SOllivier Robert    u_long  cl_samples;           /* samples for median filter */
1769c2daa00SOllivier Robert    u_long  cl_keep;              /* samples for median filter to keep */
1779c2daa00SOllivier Robert         median filter parameters - smoothing and rejection of bad samples
1789c2daa00SOllivier Robert  } clockinfo[] = {
1799c2daa00SOllivier Robert  ...,&lt;other clocks&gt;,...
1809c2daa00SOllivier Robert  { &lt; your parameters&gt; },
1819c2daa00SOllivier Robert  };
1829c2daa00SOllivier Robert
1839c2daa00SOllivier Robert</pre>
1849c2daa00SOllivier Robert				</ul>
1859c2daa00SOllivier Robert		</ol>
1869c2daa00SOllivier Robert		<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>
1879c2daa00SOllivier Robert		<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>
188ea906c41SOllivier Robert		<p>For questions: <a href="mailto:%20kardel <AT> acm.org">kardel
189ea906c41SOllivier Robert				<AT>
190ea906c41SOllivier Robert				acm.org</a>.</p>
1919c2daa00SOllivier Robert		<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).</p>
1929c2daa00SOllivier Robert		<hr>
1939c2daa00SOllivier Robert		<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
1949c2daa00SOllivier Robert	</body>
1959c2daa00SOllivier Robert
1969c2daa00SOllivier Robert	<body></body>
1979c2daa00SOllivier Robert
1989c2daa00SOllivier Robert</html>