summaryrefslogtreecommitdiffstats
path: root/usr.sbin/xntpd/doc/README.irig
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/xntpd/doc/README.irig')
-rw-r--r--usr.sbin/xntpd/doc/README.irig306
1 files changed, 306 insertions, 0 deletions
diff --git a/usr.sbin/xntpd/doc/README.irig b/usr.sbin/xntpd/doc/README.irig
new file mode 100644
index 0000000..f293f4c
--- /dev/null
+++ b/usr.sbin/xntpd/doc/README.irig
@@ -0,0 +1,306 @@
+ Audio IRIG Receiver for Precision Timekeeping
+
+ Revised 20 September 1993
+
+Note: This information file is included in both the BSD audio driver
+distribution (bsd_audio.tar.Z) and NTP Version 3 distribution
+(xntp3.tar.Z) as the file README.irig. Both distributions can be
+obtained via anonymous ftp from louie.udel.edu in the directory pub/ntp.
+
+1. Introduction
+
+This software distribution includes modifications to the BSD audio
+driver for the Sun SPARCstation written by Van Jacobson and
+collaborators at Lawrence Berkeley National Laboratory. The
+modifications provide for the connection of a standard Inter-Range
+Instrumentation Group (IRIG) timecode signal generator and the decoding
+of the signal to produce data sufficient to synchronize a host clock to
+the IRIG signal. There are several timing receivers now on the market
+that can produce IRIG signals, including those made by Austron,
+TrueTime, Odetics and Spectracom, among others. These data can be used
+to precisely synchronize the host computer clock to within a few
+microseconds without requiring level converters or pulse generators
+necessary with the one-pulse-per-second signals also produced by these
+receivers. The current implementation of the Network Time Protocol
+Version 3 supports the modified BSD driver when installed in the SunOS
+4.1.x kernel.
+
+The specific IRIG signal format supported by the driver is designated
+IRIG-B. It consists of an amplitude-modulated 1000-Hz sinewave, where
+each symbol is encoded as ten full carrier cycles, or 10 ms in duration.
+The symbols are distinguished using a pulse-width code, where 2 ms
+corresponds to logic zero, 5 ms to logic one and 8 ms to a position
+identifier used for symbol synchronization. The complete IRIG-B message
+consists of a frame of ten fields, each field consisting of a nine
+information symbols followed by a position identifier for a total frame
+duration of one second. The first symbol in the frame is also a position
+identifier to facilitate frame synchronization.
+
+The IRIG-B signal encodes the day of year and time of day in binary-
+coded decimal (BCD) format, together with a set of control functions,
+which are not used by the driver, but included in the raw binary
+timecode. Either the BCD timecode or the combined raw timecode and BCD
+timecode can be returned in response to a read() system call. The BCD
+timecode is in handy ASCII format: "ddd hh:mm:ss*" for convenience in
+client programs. In this format the "*" status character is " " when the
+driver is operating normally and "?" when errors may be present (see
+below). In order to reduce residual errors to the greatest extent
+possible, the driver computes a timestamp based on the value of the
+kernel clock at the on-time epoch of the IRIG-B signal. In addition, the
+driver automatically adjusts for slowly varying amplitude levels of the
+IRIG-B signal and suppresses noise transients.
+
+In operation the IRIG driver interprets the IRIG-B signal in real time,
+synchronizes to the signal, demodulates the data bits and prepares the
+data to be read later. At the on-time epoch a timestamp is captured from
+the kernel clock and adjusted for the phase of the IRIG carrier signal
+relative to the 8-kHz codec sample clock. When a client program issues a
+read() request, the most recent timecode data, including a status byte
+and the corrected timestamp, are stored in a structure and returned to
+the caller. Depending on the frequency with which the driver is called,
+this may result in old data or duplicate data or even invalid data,
+should the driver be called before it has computed its first timestamp.
+
+In practice, the resulting ambiguity causes few problems. The caller
+converts the ASCII timecode returned by a read() system call to Unix
+timeval format and subtracts it from the kernel timestamp provided by
+the driver. The result is an adjustment that can be subtracted from the
+kernel time, as returned in a gettimeofday() call, for example, to
+correct for the deviation between IRIG time and kernel time. The result
+can always be relied on to within plus/minus 128 microseconds, the audio
+codec sampling interval, and ordinarily to within a few microseconds, as
+determined by the interpolation algorithm.
+
+2. Programming Interface
+
+The IRIG driver modifications are integrated in the BSD audio driver
+bsd_audio.c without affecting its usual functions in transmitting and
+receiving ordinary speech, except when enabled by specific ioctl()
+system calls. However, the driver cannot be used for both speech and
+IRIG signals at the same time. Once activated by a designated ioctl()
+call, the driver remains active until it is explicitly deactivated by
+another ioctl() call. This allows applications to configure the audio
+device and pass the pre-configured driver to other applications. Since
+the driver is currently only a receiver, it does not affect the
+operation of the BSD audio output driver.
+
+Data are read using the standard read() system call. Since the output
+formats have constant lengths, the application receives the data into a
+fixed-length buffer or structure. The read() call never blocks; it
+simply returns the most recent IRIG data received during the last
+second. It may happen that, due to unavoidable race conditions in the
+kernel, data for other than the most recent second are returned. The
+driver's internal data structure is updated as an atomic unit; thus, the
+entire structure is valid, even if it contains old data. This should
+cause no problems, since in the intended application the driver is
+called at regular intervals by a time-synchronization daemon such as
+NTP. The daemon can determine the validity of the time indication by
+checking the timecode or status byte returned with the data.
+
+The header file bsd_audioirig.h defines the irig_time structure and
+ioctl() codes used by the driver. Following are those codes specific to
+the IRIG function of the driver. Unless indicated otherwise, the (third)
+argument of the ioctl() system call points to an integer or string.
+
+AUDIO_IRIG_OPEN
+
+ This command activates the IRIG receiver. The audio driver must be
+ opened with this command before other commands can be issued. The
+ argument is ignored. When the IRIG receiver is initialized, all
+ internal data are purged and any buffered data are lost.
+
+AUDIO_IRIG_CLOSE
+
+ This command deactivates the IRIG receiver. The argument is
+ ignored. The buffers are purged and any buffered time data are
+ lost. The original BSD audio driver functions are enabled and it
+ resumes operating normally.
+
+AUDIO_IRIG_SETFORMAT
+
+ The argument is a pointer to an integer designating the output
+ format for the IRIG data. There are currently two formats defined,
+ 0 (default) and 1. If an invalid format is selected, the default
+ format is used.
+
+The data returned by a read() system call in format 0 is a character
+string in the format "ddd hh:mm:ss*\n", which consists of 13 ASCII
+characters followed by a newline terminator for a total of 14
+characters. The "*" status character is an ASCII space " " if the status
+byte determined by the driver is zero and "?" if not. This format is
+intended to be used with simple user programs that care only about the
+time to the nearest second.
+The data returned by a read() system call in format 1 is a structure
+defined in the bsd_audioirig.h header file:
+
+ struct irig_time {
+ struct timeval stamp; /* timestamp */
+ u_char bits[13]; /* 100 irig data bits */
+ u_char status; /* status byte */
+ char time[14]; /* time string */
+ };
+
+The irig-time.stamp is a pair of 32-bit longwords in Unix timeval
+format, as defined in the sys/time.h header file. The first word is the
+number of seconds since 1 January 1970, while the second is the number
+of microseconds in the current second. The timestamp is captured at the
+most recent on-time instant of the IRIG timecode and applies to all
+other values returned in the irig_time structure.
+
+The irig_time.bits[13] is a vector of 13 bytes to hold the 100-bit,
+zero-padded raw binary timecode, packed 8 symbols per byte. The symbol
+encoding maps IRIG one to 1 and both IRIG zero and IRIG position
+identifier to 0. The order of encoding is illustrated by the following
+diagram (the padding bits are represented by xxxx, which are set to
+zero):
+
+IRIG symbol number 00000000001111111111 . . . 8888889999999999xxxx
+ 01234567890123456789 . . . 4567890123456789xxxx
+ -----------------------------------------------
+bits byte number <--00--><--01--><---- ----><--11--><--12-->
+bits bit in byte 01234567012345670123 . . . 45670123456701234567
+
+The irig_time.status is a single byte with bits defined in the
+bsd_audioirig.h header file. In ordinary operation all bits of the
+status byte are zero and the " " status character is set in the ASCII
+timecode. If any of these bits are nonzero, the "?" status character is
+set in the ASCII timecode.
+
+AUDIO_IRIG_BADSIGNAL
+
+ The signal amplitude is outside tolerance limits, either in
+ amplitude or modulation depth. The indicated time may or may not be
+ in error. If the signal is too high, it may be clipped by the
+ codec, so that the pulse width cannot be reliably determined. If
+ too low, it may be obscured by noise. The nominal expectation is
+ that the peak amplitude of the signal be maintained by the codec
+ AGC at about 10 dB below the clipping level and that the modulation
+ index be at least 0.5 (6 dB).
+
+AUDIO_IRIG_BADDATA
+
+ An invalid hex code (A through F) has been found where BCD data is
+ expected. The ASCII representation of the invalid code is set to
+ "?". Errors of this type are most likely due to noise on the IRIG
+ signal due to ground loops, coupling to other noise sources, etc.
+
+AUDIO_IRIG_BADSYNC
+
+ A code element has been found where a position identifier should be
+ or a position identifier has been found where a code element should
+ be. The time is meaningless and should be disregarded. Errors of
+ this type can be due to severe noise on the IRIG signal due to
+ ground loops, coupling to other noise sources, etc., or during
+ initial acquisition of the signal.
+
+AUDIO_IRIG_BADCLOCK
+
+ Some IRIG timecode generators can indicate whether or not the
+ generator is operating correctly or synchronized to its source of
+ standard time using a designated field in the raw binary timecode.
+ Where such information is available and the IRIG decoder can detect
+ it, this bit is set when the generator reports anything except
+ normal operating conditions.
+
+AUDIO_IRIG_OLDDATA
+
+ The IRIG time has not changed since the last time it was returned
+ in a read() call. This is not normally considered an error, unless
+ it persists for longer than a few seconds, in which case it
+ probably indicates a hardware problem.
+
+The irig_time.time[14] vector is a character string in the format "ddd
+hh:mm:ss*\0", which consists of 13 ASCII characters followed by a zero
+terminator. The "*" status character is an ASCII space " " if the status
+byte is zero and "?" if not. This format is identical to format 0,
+except that in format 1 the time string is null-terminated.
+
+2.1. Programming Example
+
+The following pseudo-code demonstrates how the IRIG receiver may be used
+by a simple user program. Of course, real code should include error
+checking after each call to ensure the driver is communicating properly.
+It should also verify that the correct fields in the structure are being
+filled by the read() call.
+
+ include "bsd_audioirig.h"
+
+ int format = 1;
+ struct irig_time it;
+
+ Audio_fd = open("/dev/audio", O_RDONLY);
+ ioctl(Audio_fd, AUDIO_IRIG_OPEN, NULL);
+ ioctl(Audio_fd, AUDIO_IRIG_SETFORMAT,&format);
+ while (condition)
+ read(Audio_fd, &it, sizeof(it);
+ printf("%s\n", it.time);
+ ioctl(Audio_fd, AUDIO_IRIG_CLOSE, NULL);
+ close(Audio_fd);
+
+3. Implementation and Configuration Notes
+
+The signal level produced by most IRIG-equipped radios is on the order
+of a few volts peak-peak, which is far larger than the audio codec can
+accept; therefore, an attenuator in the form of a voltage divider is
+needed. The codec can handle IRIG signals at the microphone input from
+4.2mV to 230mV peak-peak. A suitable attenuator conists of a series-
+connected 100K-Ohm resistor at the input and a parallel-connected 1K-Ohm
+resistor at the output, both contained along with suitable connectors in
+a small aluminum box. The exact values of these resistors are not
+critical, since the IRIG driver includes an automatic level-adjustment
+capability.
+
+For the most accurate time using the IRIG signal and a particular radio,
+it may be necessary to adjust the time1 parameter of the fudge command
+to compensate for the codec delay and any additional delay due to IRIG
+processing in the radio itself. Since the codec samples at an 8-kHz
+rate, the average delay is about 62 usec; however, the delays due to the
+radios and IRIG signals themselves can vary. For instance, in the
+Austron recievers the IRIG delay is essentially zero, while in the
+Spectracom receivers the delay is about 240 usec relative to the 1-pps
+signal. In addition, the poll interval can be reduced from the usual 64
+seconds to 16 seconds to reduce wander of the local hardware clock.
+Finally, the prefer parameter can be used to bias the clock-selection
+algorithm to favor the IRIG time, which is ordinarily the best time
+available. For example, the following two lines in the NTP configuration
+file ntp.conf are appropriate for the Spectracom Netclock/1 WWVB
+Synchronized Clock with IRIG Option:
+
+server 127.127.6.0 prefer minpoll 4 maxpoll 4 # irig audio decoder
+fudge 127.127.6.0 time1 0.0005
+
+The time1 value of .0005 s (500 usec) was determined by actual
+measurement. Since the IRIG delay in Austron receivers is essentially
+zero, the fudge command is not necessary with these receivers. The
+correct value in case of other radios may have to be determined by
+actual measurement. A convenient way of doing this is to configure the
+PPSPPS feature in the NTP Version 3 distribution and adjust time1 until
+the 1-pps signal and IRIG signal both show the same offset.
+
+The modified BSD driver includes both the modified driver itself
+bsd_audio.c and the IRIG header file bsd_audioirig.h, as well as
+modified header files bsd_audiovar.h and bsd_audioio.h. The driver is
+installed in the same way as described in the BSD driver documentation,
+with the addition of the following define in the kernel configuration
+file:
+
+options AUDIO_IRIG # IRIG driver
+
+This causes the IRIG code to be included in the BSD driver, as well as a
+C-coded codec interrupt routine which replaces the assembly-coded
+routine and provides the IRIG functionality. While the C-coded routine
+is somewhat slower than the assembly-coded routine, the extra overhead
+is not expected to be significant. Note that the IRIG driver calls the
+kernel routine microtime() as included in the ppsclock directory of the
+NTP Version 3 distribution xntp3. It is highly recommended that this
+routine be installed in the kernel configuration as well. The
+instructions for doing this are contained in the ppsclock directory of
+the xntp3 distribution.
+
+Roy LeCates <lecates@udel.edu> and David Mills <mills@udel.edu>
+Electrical Engineering Department
+University of Delaware
+Newark, DE 19716
+302 831 8247 fax 302 831 4316
+
+24 August 1993
OpenPOWER on IntegriCloud