1132451Sroberto<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2132451Sroberto
3132451Sroberto<html>
4132451Sroberto
5182007Sroberto	<head>
6182007Sroberto		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
7182007Sroberto		<title>Making PARSE Clocks</title>
8182007Sroberto		<link href="scripts/style.css" type="text/css" rel="stylesheet">
9182007Sroberto	</head>
10132451Sroberto
11182007Sroberto	<body>
12182007Sroberto		<h3>How to build new PARSE clocks</h3>
13182007Sroberto		<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>
14280849Scy<p>Last update:
15280849Scy  <!-- #BeginDate format:En2m -->13-Oct-2010  00:33<!-- #EndDate -->
16280849Scy    UTC</p>
17182007Sroberto		<p>Prerequisites:</p>
18182007Sroberto		<ul>
19182007Sroberto			<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)
20182007Sroberto		</ul>
21182007Sroberto		<p>What to do:</p>
22182007Sroberto		<p>Make a conversion module (libparse/clk_*.c)</p>
23182007Sroberto		<ol>
24182007Sroberto			<li>What ist the time code format ?
25182007Sroberto				<ul>
26182007Sroberto					<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:
27182007Sroberto						<pre>
28132451Sroberto      struct clocktime                /* clock time broken up from time code */
29132451Sroberto      {
30132451Sroberto	long day;
31132451Sroberto	long month;
32132451Sroberto	long year;
33132451Sroberto	long hour;
34132451Sroberto	long minute;
35132451Sroberto	long second;
36132451Sroberto	long usecond;
37132451Sroberto	long utcoffset;       /* in seconds */
38132451Sroberto	time_t utcoffset;     /* true utc time instead of date/time */
39132451Sroberto	long flags;           /* current clock status */
40132451Sroberto      };
41132451Sroberto</pre>
42182007Sroberto						<p>Conversion is usually simple and straight forward. For the flags following values can be OR'ed together:</p>
43182007Sroberto						<pre>
44132451Sroberto     PARSEB_ANNOUNCE           switch time zone warning (informational only)
45132451Sroberto     PARSEB_POWERUP            no synchronisation - clock confused (must set then)
46132451Sroberto     PARSEB_NOSYNC             timecode currently not confirmed (must set then)
47132451Sroberto                               usually on reception error when there is still a
48132451Sroberto                               chance the the generated time is still ok.
49132451Sroberto
50132451Sroberto     PARSEB_DST                DST in effect (informational only)
51132451Sroberto     PARSEB_UTC                timecode contains UTC time (informational only)
52132451Sroberto     PARSEB_LEAPADD            LEAP addition warning (prior to leap happening - must set when imminent)
53132451Sroberto			       also used for time code that do not encode the
54132451Sroberto			       direction (as this is currently the default).
55132451Sroberto     PARSEB_LEAPDEL            LEAP deletion warning (prior to leap happening - must set when imminent)
56132451Sroberto     PARSEB_ALTERNATE          backup transmitter (informational only)
57132451Sroberto     PARSEB_POSITION           geographic position available (informational only)
58132451Sroberto     PARSEB_LEAPSECOND         actual leap second (this time code is the leap
59132451Sroberto                               second - informational only)
60132451Sroberto</pre>
61182007Sroberto						<p>These are feature flags denoting items that are supported by the clock:</p>
62182007Sroberto						<pre>
63132451Sroberto     PARSEB_S_LEAP             supports LEAP - might set PARSEB_LEAP
64132451Sroberto     PARSEB_S_ANTENNA          supports ANTENNA - might set PARSEB_ALTERNATE
65132451Sroberto     PARSEB_S_PPS              supports PPS time stamping
66132451Sroberto     PARSEB_S_POSITION         supports position information (GPS)
67132451Sroberto   </pre>
68182007Sroberto						<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>
69182007Sroberto						<p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in them for examples. The basic structure is:</p>
70182007Sroberto						<pre>
71132451Sroberto     struct clockformat &lt;yourclock&gt;_format = {
72132451Sroberto       lots of fields for you to fill out (see below)
73132451Sroberto     };
74132451Sroberto
75132451Sroberto     static cvt_&lt;yourclock&gt;()
76132451Sroberto       ...
77132451Sroberto     {
78132451Sroberto       if (&lt;I do not recognize my time code&gt;) {
79132451Sroberto         return CVT_NONE;
80132451Sroberto       } else {
81132451Sroberto         if (&lt;conversion into clockformat is ok&gt;) {
82132451Sroberto           &lt;set all necessary flags&gt;;
83132451Sroberto           return CVT_OK;
84132451Sroberto         } else {
85132451Sroberto           return CVT_FAIL|CVT_BADFMT;
86132451Sroberto         }
87132451Sroberto       }
88132451Sroberto</pre>
89182007Sroberto						<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>
90182007Sroberto						<pre>
91132451Srobertostruct clockformat
92132451Sroberto{
93132451Sroberto  u_long (*input)();
94132451Sroberto  /* input routine - your routine - cvt_&lt;yourclock&gt; */
95132451Sroberto  u_long (*convert)();
96132451Sroberto  /* conversion routine - your routine - cvt_&lt;yourclock&gt; */
97132451Sroberto  /* routine for handling RS232 sync events (time stamps) - usually sync_simple */
98132451Sroberto  u_long (*syncpps)(); 
99132451Sroberto  /* PPS input routine - usually pps_one */
100132451Sroberto  void           *data;
101132451Sroberto  /* local parameters - any parameters/data/configuration info your conversion
102132451Sroberto     routine might need */
103132451Sroberto  char           *name;
104132451Sroberto  /* clock format name - Name of the time code */
105132451Sroberto  unsigned short  length;
106132451Sroberto  /* maximum length of data packet for your clock format */
107132451Sroberto  u_long   flags;
108132451Sroberto /* information for the parser what to look for */
109132451Sroberto};
110132451Sroberto</pre>
111182007Sroberto						<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>
112182007Sroberto						<p>In order to make your clk_*.c file usable a reference to the clockformat structure must be put into parse_conf.c.</p>
113182007Sroberto				</ul>
114182007Sroberto			<li>TTY setup and initialisation/configuration will be done in ntpd/refclock_parse.c.
115182007Sroberto				<ul>
116182007Sroberto					<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.
117182007Sroberto					<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)
118182007Sroberto						<pre>
119132451Sroberto   struct clockinfo
120132451Sroberto     {
121132451Sroberto      u_long  cl_flags;             /* operation flags (io modes) */
122132451Sroberto	 PARSE_F_PPSPPS       use loopfilter PPS code (CIOGETEV)
123132451Sroberto	 PARSE_F_PPSONSECOND  PPS pulses are on second
124132451Sroberto	 usually flags stay 0 as they are used only for special setups
125132451Sroberto
126132451Sroberto    void  (*cl_poll)();           /* active poll routine */
127132451Sroberto         The routine to call when the clock needs data sent to it in order to
128132451Sroberto         get a time code from the clock (e.g. Trimble clock)
129132451Sroberto
130132451Sroberto    int   (*cl_init)();           /* active poll init routine */
131132451Sroberto         The routine to call for very special initializations.
132132451Sroberto
133132451Sroberto    void  (*cl_event)();          /* special event handling (e.g. reset clock) */
134132451Sroberto         What to do, when an event happens - used to re-initialize clocks on timeout.
135132451Sroberto
136132451Sroberto    void  (*cl_end)();            /* active poll end routine */
137132451Sroberto         The routine to call to undo any special initialisation (free memory/timers)
138132451Sroberto
139132451Sroberto    void   *cl_data;              /* local data area for &quot;poll&quot; mechanism */
140132451Sroberto         local data for polling routines
141132451Sroberto
142132451Sroberto    u_fp    cl_rootdelay;         /* rootdelay */
143132451Sroberto         NTP rootdelay estimate (usually 0)
144132451Sroberto
145132451Sroberto	     u_long  cl_basedelay;         /* current offset - unsigned l_fp
146132451Sroberto                                              fractional part (fraction) by
147132451Sroberto                                              which the RS232 time code is
148132451Sroberto                                              delayed from the actual time. */
149132451Sroberto
150132451Sroberto    u_long  cl_ppsdelay;          /* current PPS offset - unsigned l_fp fractional
151132451Sroberto         time (fraction) by which the PPS time stamp is delayed (usually 0)
152132451Sroberto   part */
153132451Sroberto
154132451Sroberto    char   *cl_id;                /* ID code (usually &quot;DCF&quot;) */
155132451Sroberto         Refclock id - (max 4 chars)
156132451Sroberto
157132451Sroberto    char   *cl_description;       /* device name */
158132451Sroberto         Name of this device.
159132451Sroberto
160132451Sroberto    char   *cl_format;            /* fixed format */
161132451Sroberto         If the data format cann not ne detected automatically this is the name
162132451Sroberto	 as in clk_*.c clockformat.
163132451Sroberto
164132451Sroberto    u_char  cl_type;              /* clock type (ntp control) */
165132451Sroberto         Type if clock as in clock status word (ntp control messages) - usually 0
166132451Sroberto	 
167132451Sroberto    u_long  cl_maxunsync;         /* time to trust oscillator after losing synch
168132451Sroberto  */
169132451Sroberto         seconds a clock can be trusted after losing synchronisation.
170132451Sroberto
171132451Sroberto    u_long  cl_speed;             /* terminal input &amp; output baudrate */
172132451Sroberto    u_long  cl_cflag;             /* terminal io flags */
173132451Sroberto    u_long  cl_iflag;             /* terminal io flags */
174132451Sroberto    u_long  cl_oflag;             /* terminal io flags */
175132451Sroberto    u_long  cl_lflag;             /* terminal io flags */
176132451Sroberto         termio*.h tty modes.
177132451Sroberto
178132451Sroberto    u_long  cl_samples;           /* samples for median filter */
179132451Sroberto    u_long  cl_keep;              /* samples for median filter to keep */
180132451Sroberto         median filter parameters - smoothing and rejection of bad samples
181132451Sroberto  } clockinfo[] = {
182132451Sroberto  ...,&lt;other clocks&gt;,...
183132451Sroberto  { &lt; your parameters&gt; },
184132451Sroberto  };
185132451Sroberto
186132451Sroberto</pre>
187182007Sroberto				</ul>
188182007Sroberto		</ol>
189182007Sroberto		<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>
190182007Sroberto		<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>
191280849Scy		<p>For questions: <a href="mailto:%20kardel AT acm.org">kardel@acm.org</a>.</p>
192182007Sroberto		<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>
193182007Sroberto		<hr>
194182007Sroberto		<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
195182007Sroberto	</body>
196132451Sroberto
197182007Sroberto	<body></body>
198132451Sroberto
199280849Scy</html>
200