1270310Sse<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2270310Sse 343334Syokota<html> 443334Syokota 543334Syokota <head> 643334Syokota <meta http-equiv="content-type" content="text/html;charset=iso-8859-1"> 743334Syokota <title>Making PARSE Clocks</title> 843334Syokota <link href="scripts/style.css" type="text/css" rel="stylesheet"> 943334Syokota </head> 1043334Syokota 1143334Syokota <body> 12270310Sse <h3>How to build new PARSE clocks</h3> 1343334Syokota <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> 14270310Sse <p>Prerequisites:</p> 15270310Sse <ul> 16270310Sse <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) 1743334Syokota </ul> 18270310Sse <p>What to do:</p> 1943334Syokota <p>Make a conversion module (libparse/clk_*.c)</p> 20270310Sse <ol> 21270310Sse <li>What ist the time code format ? 22270310Sse <ul> 2343334Syokota <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: 2443334Syokota <pre> 2543334Syokota struct clocktime /* clock time broken up from time code */ 2643334Syokota { 2743334Syokota long day; 2843334Syokota long month; 2943334Syokota long year; 3043334Syokota long hour; 3143334Syokota long minute; 3243334Syokota long second; 3343334Syokota long usecond; 3443334Syokota long utcoffset; /* in seconds */ 35270310Sse time_t utcoffset; /* true utc time instead of date/time */ 36270310Sse long flags; /* current clock status */ 3743334Syokota }; 3843334Syokota</pre> 3943334Syokota <p>Conversion is usually simple and straight forward. For the flags following values can be OR'ed together:</p> 4043334Syokota <pre> 4143334Syokota PARSEB_ANNOUNCE switch time zone warning (informational only) 4243334Syokota PARSEB_POWERUP no synchronisation - clock confused (must set then) 4343334Syokota PARSEB_NOSYNC timecode currently not confirmed (must set then) 4443334Syokota usually on reception error when there is still a 4543334Syokota chance the the generated time is still ok. 46270310Sse 47270310Sse PARSEB_DST DST in effect (informational only) 48270310Sse PARSEB_UTC timecode contains UTC time (informational only) 49270310Sse PARSEB_LEAPADD LEAP addition warning (prior to leap happening - must set when imminent) 50270310Sse also used for time code that do not encode the 5143334Syokota direction (as this is currently the default). 52270310Sse PARSEB_LEAPDEL LEAP deletion warning (prior to leap happening - must set when imminent) 5343334Syokota PARSEB_ALTERNATE backup transmitter (informational only) 5443334Syokota PARSEB_POSITION geographic position available (informational only) 5543334Syokota PARSEB_LEAPSECOND actual leap second (this time code is the leap 5643334Syokota second - informational only) 5743334Syokota</pre> 5843334Syokota <p>These are feature flags denoting items that are supported by the clock:</p> 59270310Sse <pre> 60166500Sphilip PARSEB_S_LEAP supports LEAP - might set PARSEB_LEAP 61166500Sphilip PARSEB_S_ANTENNA supports ANTENNA - might set PARSEB_ALTERNATE 6243334Syokota PARSEB_S_PPS supports PPS time stamping 6343334Syokota PARSEB_S_POSITION supports position information (GPS) 6443334Syokota </pre> 6543334Syokota <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> 6643334Syokota <p>Conversion is done in the cvt_* routine in parse/clk_*.c files. look in them for examples. The basic structure is:</p> 6743334Syokota <pre> 6843334Syokota struct clockformat <yourclock>_format = { 6943334Syokota lots of fields for you to fill out (see below) 7043334Syokota }; 7143334Syokota 7243334Syokota static cvt_<yourclock>() 7343334Syokota ... 7443334Syokota { 7543334Syokota if (<I do not recognize my time code>) { 7643334Syokota return CVT_NONE; 7743334Syokota } else { 7843334Syokota if (<conversion into clockformat is ok>) { 7943334Syokota <set all necessary flags>; 8043334Syokota return CVT_OK; 8143334Syokota } else { 8243334Syokota return CVT_FAIL|CVT_BADFMT; 8343334Syokota } 8443334Syokota } 8543334Syokota</pre> 8643334Syokota <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> 8743334Syokota <pre> 8843334Syokotastruct clockformat 8943334Syokota{ 9043334Syokota u_long (*input)(); 9143334Syokota /* input routine - your routine - cvt_<yourclock> */ 9243334Syokota u_long (*convert)(); 9343334Syokota /* conversion routine - your routine - cvt_<yourclock> */ 9443334Syokota /* routine for handling RS232 sync events (time stamps) - usually sync_simple */ 9543334Syokota u_long (*syncpps)(); 9643334Syokota /* PPS input routine - usually pps_one */ 9743334Syokota void *data; 9843334Syokota /* local parameters - any parameters/data/configuration info your conversion 9943334Syokota routine might need */ 10043334Syokota char *name; 10174119Sache /* clock format name - Name of the time code */ 10243334Syokota unsigned short length; 10343334Syokota /* maximum length of data packet for your clock format */ 10443334Syokota u_long flags; 10543334Syokota /* information for the parser what to look for */ 10643334Syokota}; 10743334Syokota</pre> 10843334Syokota <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> 10943334Syokota <p>In order to make your clk_*.c file usable a reference to the clockformat structure must be put into parse_conf.c.</p> 11043334Syokota </ul> 11174119Sache <li>TTY setup and initialisation/configuration will be done in ntpd/refclock_parse.c. 112270310Sse <ul> 11343334Syokota <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. 11443334Syokota <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) 11543334Syokota <pre> 11643334Syokota struct clockinfo 11743334Syokota { 118 u_long cl_flags; /* operation flags (io modes) */ 119 PARSE_F_PPSPPS use loopfilter PPS code (CIOGETEV) 120 PARSE_F_PPSONSECOND PPS pulses are on second 121 usually flags stay 0 as they are used only for special setups 122 123 void (*cl_poll)(); /* active poll routine */ 124 The routine to call when the clock needs data sent to it in order to 125 get a time code from the clock (e.g. Trimble clock) 126 127 int (*cl_init)(); /* active poll init routine */ 128 The routine to call for very special initializations. 129 130 void (*cl_event)(); /* special event handling (e.g. reset clock) */ 131 What to do, when an event happens - used to re-initialize clocks on timeout. 132 133 void (*cl_end)(); /* active poll end routine */ 134 The routine to call to undo any special initialisation (free memory/timers) 135 136 void *cl_data; /* local data area for "poll" mechanism */ 137 local data for polling routines 138 139 u_fp cl_rootdelay; /* rootdelay */ 140 NTP rootdelay estimate (usually 0) 141 142 u_long cl_basedelay; /* current offset - unsigned l_fp 143 fractional part (fraction) by 144 which the RS232 time code is 145 delayed from the actual time. */ 146 147 u_long cl_ppsdelay; /* current PPS offset - unsigned l_fp fractional 148 time (fraction) by which the PPS time stamp is delayed (usually 0) 149 part */ 150 151 char *cl_id; /* ID code (usually "DCF") */ 152 Refclock id - (max 4 chars) 153 154 char *cl_description; /* device name */ 155 Name of this device. 156 157 char *cl_format; /* fixed format */ 158 If the data format cann not ne detected automatically this is the name 159 as in clk_*.c clockformat. 160 161 u_char cl_type; /* clock type (ntp control) */ 162 Type if clock as in clock status word (ntp control messages) - usually 0 163 164 u_long cl_maxunsync; /* time to trust oscillator after losing synch 165 */ 166 seconds a clock can be trusted after losing synchronisation. 167 168 u_long cl_speed; /* terminal input & output baudrate */ 169 u_long cl_cflag; /* terminal io flags */ 170 u_long cl_iflag; /* terminal io flags */ 171 u_long cl_oflag; /* terminal io flags */ 172 u_long cl_lflag; /* terminal io flags */ 173 termio*.h tty modes. 174 175 u_long cl_samples; /* samples for median filter */ 176 u_long cl_keep; /* samples for median filter to keep */ 177 median filter parameters - smoothing and rejection of bad samples 178 } clockinfo[] = { 179 ...,<other clocks>,... 180 { < your parameters> }, 181 }; 182 183</pre> 184 </ul> 185 </ol> 186 <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> 187 <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> 188 <p>For questions: <a href="mailto:%20kardel <AT> acm.org">kardel 189 <AT> 190 acm.org</a>.</p> 191 <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> 192 <hr> 193 <script type="text/javascript" language="javascript" src="scripts/footer.txt"></script> 194 </body> 195 196 <body></body> 197 198</html>