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