Home | History | Annotate | Line # | Download | only in html
      1      1.1    kardel <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
      2      1.1    kardel 
      3      1.1    kardel <html>
      4      1.1    kardel 
      5      1.1    kardel 	<head>
      6      1.1    kardel 		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
      7      1.1    kardel 		<title>Making PARSE Clocks</title>
      8      1.1    kardel 		<link href="scripts/style.css" type="text/css" rel="stylesheet">
      9      1.1    kardel 	</head>
     10      1.1    kardel 
     11      1.1    kardel 	<body>
     12      1.1    kardel 		<h3>How to build new PARSE clocks</h3>
     13      1.1    kardel 		<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  1.1.1.3  christos <p>Last update:
     15  1.1.1.3  christos   <!-- #BeginDate format:En2m -->13-Oct-2010  00:33<!-- #EndDate -->
     16  1.1.1.3  christos     UTC</p>
     17      1.1    kardel 		<p>Prerequisites:</p>
     18      1.1    kardel 		<ul>
     19      1.1    kardel 			<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)
     20      1.1    kardel 		</ul>
     21      1.1    kardel 		<p>What to do:</p>
     22      1.1    kardel 		<p>Make a conversion module (libparse/clk_*.c)</p>
     23      1.1    kardel 		<ol>
     24      1.1    kardel 			<li>What ist the time code format ?
     25      1.1    kardel 				<ul>
     26      1.1    kardel 					<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:
     27      1.1    kardel 						<pre>
     28      1.1    kardel       struct clocktime                /* clock time broken up from time code */
     29      1.1    kardel       {
     30      1.1    kardel 	long day;
     31      1.1    kardel 	long month;
     32      1.1    kardel 	long year;
     33      1.1    kardel 	long hour;
     34      1.1    kardel 	long minute;
     35      1.1    kardel 	long second;
     36      1.1    kardel 	long usecond;
     37      1.1    kardel 	long utcoffset;       /* in seconds */
     38      1.1    kardel 	time_t utcoffset;     /* true utc time instead of date/time */
     39      1.1    kardel 	long flags;           /* current clock status */
     40      1.1    kardel       };
     41      1.1    kardel </pre>
     42      1.1    kardel 						<p>Conversion is usually simple and straight forward. For the flags following values can be OR'ed together:</p>
     43      1.1    kardel 						<pre>
     44      1.1    kardel      PARSEB_ANNOUNCE           switch time zone warning (informational only)
     45      1.1    kardel      PARSEB_POWERUP            no synchronisation - clock confused (must set then)
     46      1.1    kardel      PARSEB_NOSYNC             timecode currently not confirmed (must set then)
     47      1.1    kardel                                usually on reception error when there is still a
     48      1.1    kardel                                chance the the generated time is still ok.
     49      1.1    kardel 
     50      1.1    kardel      PARSEB_DST                DST in effect (informational only)
     51      1.1    kardel      PARSEB_UTC                timecode contains UTC time (informational only)
     52      1.1    kardel      PARSEB_LEAPADD            LEAP addition warning (prior to leap happening - must set when imminent)
     53      1.1    kardel 			       also used for time code that do not encode the
     54      1.1    kardel 			       direction (as this is currently the default).
     55      1.1    kardel      PARSEB_LEAPDEL            LEAP deletion warning (prior to leap happening - must set when imminent)
     56      1.1    kardel      PARSEB_ALTERNATE          backup transmitter (informational only)
     57      1.1    kardel      PARSEB_POSITION           geographic position available (informational only)
     58      1.1    kardel      PARSEB_LEAPSECOND         actual leap second (this time code is the leap
     59      1.1    kardel                                second - informational only)
     60      1.1    kardel </pre>
     61      1.1    kardel 						<p>These are feature flags denoting items that are supported by the clock:</p>
     62      1.1    kardel 						<pre>
     63      1.1    kardel      PARSEB_S_LEAP             supports LEAP - might set PARSEB_LEAP
     64      1.1    kardel      PARSEB_S_ANTENNA          supports ANTENNA - might set PARSEB_ALTERNATE
     65      1.1    kardel      PARSEB_S_PPS              supports PPS time stamping
     66      1.1    kardel      PARSEB_S_POSITION         supports position information (GPS)
     67      1.1    kardel    </pre>
     68      1.1    kardel 						<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>
     69      1.1    kardel 						<p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in them for examples. The basic structure is:</p>
     70      1.1    kardel 						<pre>
     71      1.1    kardel      struct clockformat &lt;yourclock&gt;_format = {
     72      1.1    kardel        lots of fields for you to fill out (see below)
     73      1.1    kardel      };
     74      1.1    kardel 
     75      1.1    kardel      static cvt_&lt;yourclock&gt;()
     76      1.1    kardel        ...
     77      1.1    kardel      {
     78      1.1    kardel        if (&lt;I do not recognize my time code&gt;) {
     79      1.1    kardel          return CVT_NONE;
     80      1.1    kardel        } else {
     81      1.1    kardel          if (&lt;conversion into clockformat is ok&gt;) {
     82      1.1    kardel            &lt;set all necessary flags&gt;;
     83      1.1    kardel            return CVT_OK;
     84      1.1    kardel          } else {
     85      1.1    kardel            return CVT_FAIL|CVT_BADFMT;
     86      1.1    kardel          }
     87      1.1    kardel        }
     88      1.1    kardel </pre>
     89      1.1    kardel 						<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>
     90      1.1    kardel 						<pre>
     91      1.1    kardel struct clockformat
     92      1.1    kardel {
     93      1.1    kardel   u_long (*input)();
     94      1.1    kardel   /* input routine - your routine - cvt_&lt;yourclock&gt; */
     95      1.1    kardel   u_long (*convert)();
     96      1.1    kardel   /* conversion routine - your routine - cvt_&lt;yourclock&gt; */
     97      1.1    kardel   /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
     98      1.1    kardel   u_long (*syncpps)(); 
     99      1.1    kardel   /* PPS input routine - usually pps_one */
    100      1.1    kardel   void           *data;
    101      1.1    kardel   /* local parameters - any parameters/data/configuration info your conversion
    102      1.1    kardel      routine might need */
    103      1.1    kardel   char           *name;
    104      1.1    kardel   /* clock format name - Name of the time code */
    105      1.1    kardel   unsigned short  length;
    106      1.1    kardel   /* maximum length of data packet for your clock format */
    107      1.1    kardel   u_long   flags;
    108      1.1    kardel  /* information for the parser what to look for */
    109      1.1    kardel };
    110      1.1    kardel </pre>
    111      1.1    kardel 						<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>
    112      1.1    kardel 						<p>In order to make your clk_*.c file usable a reference to the clockformat structure must be put into parse_conf.c.</p>
    113      1.1    kardel 				</ul>
    114      1.1    kardel 			<li>TTY setup and initialisation/configuration will be done in ntpd/refclock_parse.c.
    115      1.1    kardel 				<ul>
    116      1.1    kardel 					<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.
    117      1.1    kardel 					<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)
    118      1.1    kardel 						<pre>
    119      1.1    kardel    struct clockinfo
    120      1.1    kardel      {
    121      1.1    kardel       u_long  cl_flags;             /* operation flags (io modes) */
    122      1.1    kardel 	 PARSE_F_PPSPPS       use loopfilter PPS code (CIOGETEV)
    123      1.1    kardel 	 PARSE_F_PPSONSECOND  PPS pulses are on second
    124      1.1    kardel 	 usually flags stay 0 as they are used only for special setups
    125      1.1    kardel 
    126      1.1    kardel     void  (*cl_poll)();           /* active poll routine */
    127      1.1    kardel          The routine to call when the clock needs data sent to it in order to
    128      1.1    kardel          get a time code from the clock (e.g. Trimble clock)
    129      1.1    kardel 
    130      1.1    kardel     int   (*cl_init)();           /* active poll init routine */
    131      1.1    kardel          The routine to call for very special initializations.
    132      1.1    kardel 
    133      1.1    kardel     void  (*cl_event)();          /* special event handling (e.g. reset clock) */
    134      1.1    kardel          What to do, when an event happens - used to re-initialize clocks on timeout.
    135      1.1    kardel 
    136      1.1    kardel     void  (*cl_end)();            /* active poll end routine */
    137      1.1    kardel          The routine to call to undo any special initialisation (free memory/timers)
    138      1.1    kardel 
    139      1.1    kardel     void   *cl_data;              /* local data area for &quot;poll&quot; mechanism */
    140      1.1    kardel          local data for polling routines
    141      1.1    kardel 
    142      1.1    kardel     u_fp    cl_rootdelay;         /* rootdelay */
    143      1.1    kardel          NTP rootdelay estimate (usually 0)
    144      1.1    kardel 
    145      1.1    kardel 	     u_long  cl_basedelay;         /* current offset - unsigned l_fp
    146      1.1    kardel                                               fractional part (fraction) by
    147      1.1    kardel                                               which the RS232 time code is
    148      1.1    kardel                                               delayed from the actual time. */
    149      1.1    kardel 
    150      1.1    kardel     u_long  cl_ppsdelay;          /* current PPS offset - unsigned l_fp fractional
    151      1.1    kardel          time (fraction) by which the PPS time stamp is delayed (usually 0)
    152      1.1    kardel    part */
    153      1.1    kardel 
    154      1.1    kardel     char   *cl_id;                /* ID code (usually &quot;DCF&quot;) */
    155      1.1    kardel          Refclock id - (max 4 chars)
    156      1.1    kardel 
    157      1.1    kardel     char   *cl_description;       /* device name */
    158      1.1    kardel          Name of this device.
    159      1.1    kardel 
    160      1.1    kardel     char   *cl_format;            /* fixed format */
    161      1.1    kardel          If the data format cann not ne detected automatically this is the name
    162      1.1    kardel 	 as in clk_*.c clockformat.
    163      1.1    kardel 
    164      1.1    kardel     u_char  cl_type;              /* clock type (ntp control) */
    165      1.1    kardel          Type if clock as in clock status word (ntp control messages) - usually 0
    166      1.1    kardel 	 
    167      1.1    kardel     u_long  cl_maxunsync;         /* time to trust oscillator after losing synch
    168      1.1    kardel   */
    169      1.1    kardel          seconds a clock can be trusted after losing synchronisation.
    170      1.1    kardel 
    171      1.1    kardel     u_long  cl_speed;             /* terminal input &amp; output baudrate */
    172      1.1    kardel     u_long  cl_cflag;             /* terminal io flags */
    173      1.1    kardel     u_long  cl_iflag;             /* terminal io flags */
    174      1.1    kardel     u_long  cl_oflag;             /* terminal io flags */
    175      1.1    kardel     u_long  cl_lflag;             /* terminal io flags */
    176      1.1    kardel          termio*.h tty modes.
    177      1.1    kardel 
    178      1.1    kardel     u_long  cl_samples;           /* samples for median filter */
    179      1.1    kardel     u_long  cl_keep;              /* samples for median filter to keep */
    180      1.1    kardel          median filter parameters - smoothing and rejection of bad samples
    181      1.1    kardel   } clockinfo[] = {
    182      1.1    kardel   ...,&lt;other clocks&gt;,...
    183      1.1    kardel   { &lt; your parameters&gt; },
    184      1.1    kardel   };
    185      1.1    kardel 
    186      1.1    kardel </pre>
    187      1.1    kardel 				</ul>
    188      1.1    kardel 		</ol>
    189      1.1    kardel 		<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>
    190      1.1    kardel 		<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  1.1.1.2  christos 		<p>For questions: <a href="mailto:%20kardel AT acm.org">kardel (a] acm.org</a>.</p>
    192      1.1    kardel 		<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>
    193      1.1    kardel 		<hr>
    194      1.1    kardel 		<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
    195      1.1    kardel 	</body>
    196      1.1    kardel 
    197      1.1    kardel 	<body></body>
    198      1.1    kardel 
    199  1.1.1.2  christos </html>
    200