aboutsummaryrefslogtreecommitdiff
path: root/html/howto.htm
diff options
context:
space:
mode:
Diffstat (limited to 'html/howto.htm')
-rw-r--r--html/howto.htm320
1 files changed, 320 insertions, 0 deletions
diff --git a/html/howto.htm b/html/howto.htm
new file mode 100644
index 000000000000..6e082425ca7b
--- /dev/null
+++ b/html/howto.htm
@@ -0,0 +1,320 @@
+<html><head><title>
+How to Write a Reference Clock Driver
+</title></head><body><h3>
+How to Write a Reference Clock Driver
+</h3>
+
+<img align=left src=pic/pogo4.gif><a href=http://www.eecis.udel.edu/~mills/pictures.htm>from <i>Pogo</i>, Walt Kelly</a>
+
+<p>You need a little magic.
+<br clear=left><hr>
+
+<h4>Description</h4>
+
+<p>Reference clock support maintains the fiction that the clock is
+actually an ordinary peer in the NTP tradition, but operating at a
+synthetic stratum of zero. The entire suite of algorithms used to filter
+the received data, select the best clocks or peers and combine them to
+produce a local clock correction operate just like ordinary NTP peers.
+In this way, defective clocks can be detected and removed from the peer
+population. As no packets are exchanged with a reference clock; however,
+the transmit, receive and packet procedures are replaced with separate
+code to simulate them.
+
+<p>Radio and modem reference clocks by convention have addresses in the
+form <tt>127.127.<i>t</i>.<i>u</i></tt>, where <i>t</i> is the clock
+type and <i>u</i> in the range 0-3 is used to distinguish multiple
+instances of clocks of the same type. Most clocks require a serial port
+or special bus peripheral. The particular device is normally specified
+by adding a soft link <tt>/dev/device<i>d</i>d</tt> to the particular
+hardware device involved, where <tt><i>d</i></tt> corresponds to the
+unit number.
+
+<p>The best way to understand how the clock drivers work is to study the
+<tt>ntp_refclock.c</tt> module and one of the drivers already
+implemented, such as <tt>refclock_wwvb.c</tt>. Routines
+<tt>refclock_transmit()</tt> and <tt>refclock_receive()</tt> maintain
+the peer variables in a state analogous to a network peer and pass
+received data on through the clock filters. Routines
+<tt>refclock_peer()</tt> and <tt>refclock_unpeer()</tt> are called to
+initialize and terminate reference clock associations, should this ever
+be necessary. A set of utility routines is included to open serial
+devices, process sample data, edit input lines to extract embedded
+timestamps and to perform various debugging functions.
+
+<p>The main interface used by these routines is the
+<tt>refclockproc</tt> structure, which contains for most drivers the
+decimal equivalents of the year, day, month, hour, second and
+millisecond/microsecond decoded from the ASCII timecode. Additional
+information includes the receive timestamp, exception report, statistics
+tallies, etc. The support routines are passed a pointer to the
+<tt>peer</tt> structure, which is used for all peer-specific processing
+and contains a pointer to the <tt>refclockproc</tt> structure, which in
+turn contains a pointer to the unit structure, if used. For legacy
+purposes, a table <tt>typeunit[type][unit]</tt> contains the peer
+structure pointer for each configured clock type and unit.
+
+<p>The reference clock interface supports auxiliary functions to support
+in-stream timestamping, pulse-per-second (PPS) interfacing and precision
+time kernel support. In most cases the drivers do not need to be aware
+of them, since they are detected at autoconfigure time and loaded
+automatically when the device is opened. These include the
+<tt>tty_clk</tt> and <tt>ppsclock</tt> STREAMS modules and
+<tt>ppsapi</tt> PPS interface described in the <a href="ldisc.htm">Line
+Disciplines and Streams Modules</a> page. The <tt>tty_clk</tt> module
+reduces latency errors due to the operating system and serial port code
+in slower systems. The <tt>ppsclock</tt> module is an interface for the
+PPS signal provided by some radios. The <tt>ppsapi</tt> PPS interface
+replaces the <tt>ppsclock</tt> STREAMS module and is expected to become
+the IETF standard cross-platform interface for PPS signals. In either
+case, the PPS signal can be connected via a level converter/pulse
+generator described in the <a href = "gadget.htm"> Gadget Box PPS Level
+Converter and CHU Modem</a> page.
+
+<p>By convention, reference clock drivers are named in the form
+<tt>refclock_<i>xxxx</i>.c</tt>, where <i>xxxx</i> is a unique
+string. Each driver is assigned a unique type number, long-form driver
+name, short-form driver name, and device name. The existing assignments
+are in the <a href="refclock.htm"> Reference Clock Drivers</a> page
+and its dependencies. All drivers supported by the particular hardware
+and operating system are automatically detected in the autoconfigure
+phase and conditionally compiled. They are configured when the daemon is
+started according to the configuration file, as described in the <a
+href="config.htm"> Configuration Options </a> page.
+
+<p>The standard clock driver interface includes a set of common support
+routines some of which do such things as start and stop the device, open
+the serial port, and establish special functions such as PPS signal
+support. Other routines read and write data to the device and process
+time values. Most drivers need only a little customizing code to, for
+instance, transform idiosyncratic timecode formats to standard form,
+poll the device as necessary, and handle exception conditions. A
+standard interface is available for remote debugging and monitoring
+programs, such as <tt>ntpq</tt> and <tt>ntpdc</tt>, as well as
+the <tt>filegen</tt> facility, which can be used to record device
+status on a continuous basis.
+
+<p>The general organization of a typical clock driver includes a
+receive-interrupt routine to read a timecode from the I/O buffer and
+convert to internal format, generally in days, hours, minutes, seconds
+and fraction. Some timecode formats include provisions for leap-second
+warning and determine the clock hardware and software health. The
+interrupt routine then calls <tt>refclock_process()</tt> with these data
+and the timestamp captured at the on-time character of the timecode.
+This routine saves each sample as received in a circular buffer, which
+can store from a few up to 60 samples, in cases where the timecodes
+arrive one per second.
+
+<p>The <tt>refclock_transmit()</tt> routine in the interface is called
+by the system at intervals defined by the poll interval in the peer
+structure, generally 64 s. This routine in turn calls the transmit poll
+routine in the driver. In the intended design, the driver calls the
+<tt>refclock_receive()</tt> to process the offset samples that have
+accumulated since the last poll and produce the final offset and
+variance. The samples are processed by recursively discarding median
+outlyers until about 60 percent of samples remain, then averaging the
+surviving samples. When a reference clock must be explicitly polled to
+produce a timecode, the driver can reset the poll interval so that the
+poll routine is called a specified number of times at 1-s intervals.
+
+<p>The interface code and this documentation have been developed over
+some time and required not a little hard work converting old drivers,
+etc. Should you find success writing a driver for a new radio or modem
+service, please consider contributing it to the common good. Send the
+driver file itself and patches for the other files to Dave Mills
+(mills@udel.edu).
+
+<h4>Conventions, Fudge Factors and Flags</h4>
+
+<p>Most drivers support manual or automatic calibration for systematic
+offset bias using values encoded in the <tt>fudge</tt> configuration
+command. By convention, the <tt>time1</tt> value defines the calibration
+offset in seconds. For those drivers that support statistics collection
+using the <tt>filegen</tt> utility and the <tt>clockstats</tt> file, the
+<tt>flag4</tt> switch enables the utility. When a PPS signal is
+available, a special automatic calibration facility is provided. If the
+<tt>flag1</tt> switch is set and the PPS signal is actively disciplining
+the system time, the calibration value is automatically adjusted to
+maintain a residual offset of zero. Should the PPS signal or the prefer
+peer fail, the adjustment is frozen and the remaining drivers continue
+to discipline the system clock with a minimum of residual error.
+
+<h4>Files Which Need to be Changed</h4>
+
+<p>A new reference clock implementation needs to supply, in addition to
+the driver itself, several changes to existing files.
+
+<dl>
+
+<dt><tt>./include/ntp.h</tt>
+<dd>The reference clock type defines are used in many places. Each
+driver is assigned a unique type number. Unused numbers are clearly
+marked in the list. A unique <tt>REFCLK_<i>xxxx</i></tt>
+identification code should be recorded in the list opposite its assigned
+type number.
+
+<p><dt><tt>./libntp/clocktypes.c</tt>
+<dd>The <tt>./libntp/clktype</tt> array is used by certain display
+functions. A unique short-form name of the driver should be entered
+together with its assigned identification code.
+
+<p><dt><tt>./ntpd/ntp_control.c</tt>
+<dd>The <tt>clocktypes</tt> array is used for certain control
+message displays functions. It should be initialized with the reference
+clock class assigned to the driver, as per the NTP specification
+RFC-1305. See the <tt>./include/ntp_control.h</tt> header file for
+the assigned classes.
+
+<p><dt><tt>./ntpd/refclock_conf.c</tt>
+<dd>This file contains a list of external structure definitions which
+are conditionally defined. A new set of entries should be installed
+similar to those already in the table. The <tt>refclock_conf</tt>
+array is a set of pointers to transfer vectors in the individual
+drivers. The external name of the transfer vector should be initialized
+in correspondence with the type number.
+
+<p><dt><tt>./acconfig.h</tt>
+<dd>This is a configuration file used by the autoconfigure scheme. Add
+two lines in the form:
+
+<p><pre>
+ /* Define if we have a FOO clock */
+ #undef FOO
+</pre>
+
+<p>where FOO is the define used to cause the driver to be included in
+the distribution.
+
+<p><dt><tt>./configure.in</tt>
+<dd>This is a configuration file used by the autoconfigure scheme. Add
+lines similar to the following:
+
+<p><pre>
+ AC_MSG_CHECKING(FOO clock_description)
+ AC_ARG_ENABLE(FOO, [ --enable-FOO clock_description],
+ [ntp_ok=$enableval], [ntp_ok=$ntp_eac])
+ if test "$ntp_ok" = "yes"; then
+ ntp_refclock=yes
+ AC_DEFINE(FOO)
+ fi
+ AC_MSG_RESULT($ntp_ok)
+</pre>
+
+<p>(Note that <tt>$ntp_eac</tt> is the value from <tt>--
+{dis,en}able-all-clocks</tt> for non-PARSE clocks and
+<tt>$ntp_eacp</tt> is the value from <tt>--{dis,en}able-parse-
+clocks</tt> for PARSE clocks. See the documentation on the autoconf
+and automake tools from the GNU distributions.)
+
+<p><dt><tt>./ntpd/Makefile.am</tt>
+<dd><p>This is the makefile prototype used by the autoconfigure scheme.
+Add the driver file name to the entries already in the
+<tt>ntpd_SOURCES</tt> list.
+
+<p>Patches to <tt>automake-1.0</tt> are required for the
+autoconfigure scripts to work properly. The file <tt>automake-
+1.0.patches</tt> can be used for this purpose.
+
+<p><dt><tt>./ntpd/Makefile.am</tt>
+<dd>Do the following sequence of commands:
+
+<p><pre>
+ automake
+ autoconf
+ autoheader
+ configure
+</pre>
+
+<p>or simply run <tt>make</tt>, which will do this command sequence
+automatically.
+
+</dl>
+
+<p><h4>Interface Routine Overview</h4>
+
+<dl>
+
+<dt><tt>refclock_newpeer</tt> - initialize and start a reference
+clock
+<dd>This routine allocates and initializes the interface structure which
+supports a reference clock in the form of an ordinary NTP peer. A
+driver-specific support routine completes the initialization, if used.
+Default peer variables which identify the clock and establish its
+reference ID and stratum are set here. It returns one if success and
+zero if the clock address is invalid or already running, insufficient
+resources are available or the driver declares a bum rap.
+<p><dt><tt>refclock_unpeer</tt> - shut down a clock
+<dd>This routine is used to shut down a clock and return its resources
+to the system.
+
+<p><dt><tt>refclock_transmit</tt> - simulate the transmit procedure
+<dd>This routine implements the NTP transmit procedure for a reference
+clock. This provides a mechanism to call the driver at the NTP poll
+interval, as well as provides a reachability mechanism to detect a
+broken radio or other madness.
+
+<p><dt><tt>refclock_sample</tt> - process a pile of samples from the
+clock
+<dd>This routine converts the timecode in the form days, hours, minutes,
+seconds, milliseconds/microseconds to internal timestamp format. It then
+calculates the difference from the receive timestamp and assembles the
+samples in a shift register. It implements a recursive median filter to
+suppress spikes in the data, as well as determine a rough dispersion
+estimate. A configuration constant time adjustment
+<tt>fudgetime1</tt> can be added to the final offset to compensate
+for various systematic errors. The routine returns one if success and
+zero if failure due to invalid timecode data or very noisy offsets.
+
+<p>Note that no provision is included for the year, as provided by some
+(but not all) radio clocks. Ordinarily, the year is implicit in the Unix
+file system and hardware/software clock support, so this is ordinarily
+not a problem. Nevertheless, the absence of the year should be
+considered more a bug than a feature and may be supported in future.
+
+<p><dt><tt>refclock_receive</tt> - simulate the receive and packet
+procedures
+<dd>This routine simulates the NTP receive and packet procedures for a
+reference clock. This provides a mechanism in which the ordinary NTP
+filter, selection and combining algorithms can be used to suppress
+misbehaving radios and to mitigate between them when more than one is
+available for backup.
+
+<p><dt><tt>refclock_gtlin</tt> - groom next input line and extract
+timestamp
+<dd>This routine processes the timecode received from the clock and
+removes the parity bit and control characters. If a timestamp is present
+in the timecode, as produced by the <tt>tty_clk</tt> line
+discipline/streams module, it returns that as the timestamp; otherwise,
+it returns the buffer timestamp. The routine return code is the number
+of characters in the line.
+
+<p><dt><tt>refclock_open</tt> - open serial port for reference clock
+<dd>This routine opens a serial port for I/O and sets default options.
+It returns the file descriptor if success and zero if failure.
+
+<p><dt><tt>refclock_ioctl</tt> - set serial port control functions
+<dd>This routine attempts to hide the internal, system-specific details
+of serial ports. It can handle POSIX (<tt>termios</tt>), SYSV
+(<tt>termio</tt>) and BSD (<tt>sgtty</tt>) interfaces with
+varying degrees of success. The routine sets up the <tt>tty_clk,
+chu_clk</tt> and <tt>ppsclock</tt> streams module/line discipline,
+if compiled in the daemon and requested in the call. The routine returns
+one if success and zero if failure.
+
+<p><dt><tt>refclock_control</tt> - set and/or return clock values
+<dd>This routine is used mainly for debugging. It returns designated
+values from the interface structure that can be displayed using ntpdc
+and the clockstat command. It can also be used to initialize
+configuration variables, such as <tt>fudgetimes, fudgevalues,</tt>
+reference ID and stratum.
+
+<p><dt><tt>refclock_buginfo</tt> - return debugging info
+<dd>This routine is used mainly for debugging. It returns designated
+values from the interface structure that can be displayed using
+<tt>ntpdc</tt> and the <tt>clkbug</tt> command.
+
+</dl>
+
+<hr><a href=index.htm><img align=left src=pic/home.gif></a><address><a
+href=mailto:mills@udel.edu> David L. Mills &lt;mills@udel.edu&gt;</a>
+</address></a></body></html>