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 <yourclock>_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_<yourclock>() 76 1.1 kardel ... 77 1.1 kardel { 78 1.1 kardel if (<I do not recognize my time code>) { 79 1.1 kardel return CVT_NONE; 80 1.1 kardel } else { 81 1.1 kardel if (<conversion into clockformat is ok>) { 82 1.1 kardel <set all necessary flags>; 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_<yourclock> */ 95 1.1 kardel u_long (*convert)(); 96 1.1 kardel /* conversion routine - your routine - cvt_<yourclock> */ 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 "IP" 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 "poll" 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 "DCF") */ 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 & 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 ...,<other clocks>,... 183 1.1 kardel { < your parameters> }, 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