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 <yourclock>_format = { 729c2daa00SOllivier Robert lots of fields for you to fill out (see below) 739c2daa00SOllivier Robert }; 749c2daa00SOllivier Robert 759c2daa00SOllivier Robert static cvt_<yourclock>() 769c2daa00SOllivier Robert ... 779c2daa00SOllivier Robert { 789c2daa00SOllivier Robert if (<I do not recognize my time code>) { 799c2daa00SOllivier Robert return CVT_NONE; 809c2daa00SOllivier Robert } else { 819c2daa00SOllivier Robert if (<conversion into clockformat is ok>) { 829c2daa00SOllivier Robert <set all necessary flags>; 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_<yourclock> */ 959c2daa00SOllivier Robert u_long (*convert)(); 969c2daa00SOllivier Robert /* conversion routine - your routine - cvt_<yourclock> */ 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 "IP" 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 "poll" 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 "DCF") */ 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 & 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 ...,<other clocks>,... 1839c2daa00SOllivier Robert { < your parameters> }, 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