diff options
Diffstat (limited to 'usr.sbin/xntpd/doc/README.irig')
-rw-r--r-- | usr.sbin/xntpd/doc/README.irig | 306 |
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 |