]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
More CHU, IRIG, WWV, and WWVB fixes from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Mon, 5 Feb 2007 07:16:55 +0000 (02:16 -0500)
committerHarlan Stenn <stenn@ntp.org>
Mon, 5 Feb 2007 07:16:55 +0000 (02:16 -0500)
bk: 45c6d9e7DyO24f9CVQMD1PHZy0_Iag

ChangeLog
html/drivers/driver36.html
html/drivers/driver6.html
html/drivers/driver7.html
ntpd/refclock_chu.c
ntpd/refclock_irig.c
ntpd/refclock_wwv.c
ntpd/refclock_wwvb.c

index 0640668b56e5d9a7a1ba1ed305694347f944a1fb..3e37cb2c5dd70ef16523093f8993105d99d01a8c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,5 @@
 * [Bug 592] Trimble Thunderbolt GPS support
-* IRIG, CHU, WWV refclock improvements from Dave Mills.
+* IRIG, CHU, WWV, WWVB refclock improvements from Dave Mills.
 * [Bug 757] Lose ULONG_CONST().
 * [Bug 756] Require ANSI C (function prototypes).
 * codec (audio) and ICOM changes from Dave Mills.
index d67dc6b2e15d17fbb196edb8c97a4095e1c23c7a..6ecbec1fcbcd5ff10206ae5c899758e0cc91228c 100644 (file)
                Driver ID: <tt>WWV_AUDIO</tt><br>
                Autotune Port: <tt>/dev/icom</tt>; 1200/9600 baud, 8-bits, no parity<br>
                Audio Device: <tt>/dev/audio</tt> and <tt>/dev/audioctl</tt>
-               <h4>Description</h4>
-               This driver synchronizes the computer time using data encoded in shortwave radio transmissions from NIST time/frequency stations <a href="http://www.bldrdoc.gov/timefreq/stations/wwv.html">WWV</a> in Ft. Collins, CO, and <a href="http://www.bldrdoc.gov/timefreq/stations/wwvh.htm">WWVH</a> in Kauai, HI. Transmissions are made continuously on 2.5, 5, 10 and 15 MHz from both stations and on 20 MHz from WWV. An ordinary shortwave receiver can be tuned manually to one of these frequencies or, in the case of ICOM receivers, the receiver can be tuned automatically by the driver as propagation conditions change throughout the day and season.<p>In general and without calibration, the driver is accurate within 1 ms relative to the broadcast time when tracking a station. However, variations up to 0.5 ms can be expected due to diurnal variations in ionospheric layer height. In Newark DE, 2479 km from the transmitter, the predicted two-hop propagation delay varies from 9.3 ms in sunlight to 9.0 ms in moonlight. When not tracking the station the accuracy depends on the computer clock oscillator stability, ordinarily better than 0.5 PPM.</p>
-               <p>The driver performs a number of error checks to protect against overdriven or underdriven input signal levels, incorrect signal format or improper hardware configuration. The specific checks are detailed later in this page. Note that additional checks are done elsewhere in the reference clock interface routines. In order to assure reliable signal capture, the codec frequency error must be less than 125 PPM (.0125 percent). The <tt>tinker codec</tt> configuration command can be used to bracket the codec frequency to this range.</p>
+               <h4>Description</h4>This driver synchronizes the computer time using shortwave radio transmissions from NIST time/frequency stations <a href="http://www.bldrdoc.gov/timefreq/stations/wwv.html">WWV</a> in Ft. Collins, CO, and <a href="http://www.bldrdoc.gov/timefreq/stations/wwvh.htm">WWVH</a> in Kauai, HI. Transmissions are made continuously on 2.5, 5, 10 and 15 MHz from both stations and on 20 MHz from WWV. An ordinary shortwave receiver can be tuned manually to one of these frequencies or, in the case of ICOM receivers, the receiver can be tuned automatically by the driver as propagation conditions change throughout the day and season. The radio is connected via an optional attenuator and cable to either the microphone or line-in port of a workstation or PC.
+               <p>The driver requires an audio codec or sound card with sampling rate 8 kHz and <font face="symbol">m</font>-law companding to demodulate the data. This is the same standard as used by the telephone industry and is supported by most hardware and operating systems, including Solaris, FreeBSD and Linux, among others. In this implementation only one audio driver and codec can be supported on a single machine. In order to assure reliable signal capture, the codec frequency error must be less than 125 PPM (.0125 percent). If necessary, the <tt>tinker codec</tt> configuration command can be used to bracket the codec frequency to this range.</p>
+               <p>In general and without calibration, the driver is accurate within 1 ms relative to the broadcast time when tracking a station. However, variations up to 0.3 ms can be expected due to diurnal variations in ionospheric layer height and ray geometry. In Newark DE, 2479 km from the transmitter, the predicted two-hop propagation delay varies from 9.3 ms in sunlight to 9.0 ms in moonlight. When not tracking the station the accuracy depends on the computer clock oscillator stability, ordinarily better than 0.5 PPM.</p>
+               <p>After calibration relative to the PPS&nbsp;signal from a GPS&nbsp;receiver, the mean offset with a 2.4-GHz P4 running FreeBSD 6.1 is generally within 0.1 ms short-term with 0.4 ms jitter. The long-term mean offset varies up to 0.3 ms due to propagation path geometry variations. The processor load due to the driver is 0.4 percent on the P4.</p>
+               <p>The driver performs a number of error checks to protect against overdriven or underdriven input signal levels, incorrect signal format or improper hardware configuration. The specific checks are detailed later in this page. Note that additional checks are done elsewhere in the reference clock interface routines.</p>
                <p>This driver incorporates several features in common with other audio drivers such as described in the <a href="driver7.html">Radio CHU Audio Demodulator/Decoder</a> and the <a href="driver6.html">IRIG Audio Decoder</a> pages. They include automatic gain control (AGC), selectable audio codec port and signal monitoring capabilities. For a discussion of these common features, as well as a guide to hookup, debugging and monitoring, see the <a href="../audio.html">Reference Clock Audio Drivers</a> page.</p>
-               <p>Unlike other drivers, which can have multiple instantiations, this one supports only one. It does not seem likely that more than one audio codec would be useful in a single machine. More than one would probably chew up too much CPU time anyway.</p>
-               <h4>Overview</h4>
-               <p>The demodulation and decoding algorithms used by this driver are based on a machine language program developed for the TAPR DSP93 DSP unit, which uses the TI 320C25 DSP chip. The analysis, design and performance of the program running on this unit is described in: Mills, D.L. A precision radio clock for WWV transmissions. Electrical Engineering Report 97-8-1, University of Delaware, August 1997, 25 pp. Available from <a href="http://www.eecis.udel.edu/%7emills/reports.html">www.eecis.udel.edu/~mills/reports.htm</a>. For use in this driver, the original program was rebuilt in the C language and adapted to the NTP driver interface. The algorithms have been modified to improve performance, especially under weak signal conditions and to provide an automatic frequency and station selection feature.</p>
-               <p>As in the original program, the clock discipline is modelled as a Markov process, with probabilistic state transitions corresponding to a conventional clock and the probabilities of received decimal digits. The result is a performance level which results in very high accuracy and reliability, even under conditions when the minute beep of the signal, normally its most prominent feature, can barely be detected by ear using  a communications receiver.</p>
-               <p>The WWV signal format is described in NIST Special Publication 432 (Revised 1990). It consists of three elements, a 5-ms, 1000-Hz pulse, which occurs at the beginning of each second, a 800-ms, 1000-Hz pulse, which occurs at the beginning of each minute, and a pulse-width modulated 100-Hz subcarrier for the data bits, one bit per second. The WWVH format is identical, except that the 1000-Hz pulses are sent at 1200 Hz. Each minute encodes nine BCD digits for the time of century plus seven bits for the daylight savings time (DST) indicator, leap warning indicator and DUT1 correction.</p>
+               <h4>Technical Overview</h4>
+               <p>The driver processes 8-kHz <font face="symbol">m</font>-law companded codec samples using maximum-likelihood techniques which exploit the considerable degree of redundancy available in the broadcast signal. The WWV signal format is described in NIST Special Publication 432 (Revised 1990) and also available on the <a href="http://tf.nist.gov/stations/wwvtimecode.htm">WWV/H web site</a>. It consists of three elements, a 5-ms, 1000-Hz pulse, which occurs at the beginning of each second, a 800-ms, 1000-Hz pulse, which occurs at the beginning of each minute, and a pulse-width modulated 100-Hz subcarrier for the data bits, one bit per second. The WWVH format is identical, except that the 1000-Hz pulses are sent at 1200 Hz. Each minute encodes nine BCD digits for the time of century plus seven bits for the daylight savings time (DST) indicator, leap warning indicator and DUT1 correction.</p>
+               <p>The demodulation and decoding algorithms used by this driver are based on a machine language program developed for the TAPR DSP93 DSP unit, which uses the TI 320C25 DSP chip. The analysis, design and performance of the program for this unit is described in: Mills, D.L. A precision radio clock for WWV transmissions. Electrical Engineering Report 97-8-1, University of Delaware, August 1997, 25 pp. Available from <a href="http://www.eecis.udel.edu/%7emills/reports.html">www.eecis.udel.edu/~mills/reports.htm</a>. For use in this driver, the original program was rebuilt in the C language and adapted to the NTP driver interface. The algorithms have been modified to improve performance, especially under weak signal conditions and to provide an automatic frequency and station selection feature.</p>
+               <p>As in the original program, the clock discipline is modelled as a Markov process, with probabilistic state transitions corresponding to a conventional clock and the probabilities of received decimal digits. The result is a performance level with very high accuracy and reliability, even under conditions when the minute beep of the signal, normally its most prominent feature, can barely be detected by ear using a communications receiver.</p>
                <h4>Baseband Signal Processing</h4>
-               <p>The driver processes 8000-Hz <font face="symbol">m</font>-law companded samples from the shortwave radio. The 1000/1200-Hz pulses and 100-Hz subcarrier are first separated using a 600-Hz bandpass filter centered on 1100 Hz and a 150-Hz lowpass filter. The minute pulse is extracted using an 800-ms synchronous matched filter and pulse grooming logic which discriminates between WWV and WWVH signals and noise. The second pulse is extracted using a 5-ms FIR matched filter and 8000-stage comb filter.</p>
-               <p>The phase of the 100-Hz subcarrier relative to the second pulse is fixed at the transmitter; however, the audio stage in many radios affects the phase response at 100 Hz in unpredictable ways. The driver adjusts for each radio using two 170-ms synchronous matched filters. The I (in-phase) filter is used to demodulate the subcarrier envelope, while the Q (quadrature-phase) filter is used in a tracking loop to discipline the  demodulator phase.</p>
-               <p>A bipolar data signal is determined from the matched filter I and Q channels using a pulse-width discriminator. The discriminator samples the I channel at 15 ms (<i>n</i>),  200 ms (<i>s</i><sub>0</sub>) and 500 ms (<i>s</i><sub>1</sub>), and the envelope (RMS I and Q channels) at 200 ms (<i>e</i><sub>1</sub>) and the end of the second (<i>e</i><sub>0</sub>). The bipolar data signal is expressed 2<i>s</i><sub>1</sub> - <i>s</i><sub>0</sub> - <i>n</i>, where positive values correspond to one and negative values correspond to zero. Note that, since the signals <i>s</i><sub>0</sub> and <i>s</i><sub>1</sub> include the noise <i>n</i>, the noise component cancels out. The data bit SNR is calculated as 20 log<sub>10</sub>(<i>e</i><sub>1</sub> / <i>e</i><sub>0</sub>). If the driver has not synchronized to the minute pulse, or if the data bit amplitude <i>e</i><sub>1</sub> or SNR are below thresholds, the bit is considered invalid and the bipolar signal is forced to zero.</p>
+               <p>The 1000/1200-Hz pulses and 100-Hz subcarrier are first separated using a 600-Hz bandpass filter centered on 1100 Hz and a 150-Hz lowpass filter. The minute pulse is extracted using an 800-ms synchronous matched filter and pulse grooming logic which discriminates between WWV and WWVH signals and noise. The second pulse is extracted using a 5-ms FIR matched filter for each station and a single 8000-stage comb filter.</p>
+               <p>The phase of the 100-Hz subcarrier relative to the second pulse is fixed at the transmitter; however, the audio stage in many radios affects the phase response at 100 Hz in unpredictable ways. The driver adjusts for each radio using two 170-ms synchronous matched filters. The I (in-phase) filter is used to demodulate the subcarrier envelope, while the Q (quadrature-phase) filter is used in a type-1 phase-lock loop (PLL) to discipline the demodulator phase.</p>
+               <p>A bipolar data signal is determined from the matched filter subcarrier envelope using a pulse-width discriminator. The discriminator samples the I channel at 15 ms (<i>n</i>),  200 ms (<i>s</i><sub>0</sub>) and 500 ms (<i>s</i><sub>1</sub>), and the envelope (RMS I and Q channels) at 200 ms (<i>e</i><sub>1</sub>) and the end of the second (<i>e</i><sub>0</sub>). The bipolar data signal is expressed 2<i>s</i><sub>1</sub> - <i>s</i><sub>0</sub> - <i>n</i>, where positive values correspond to data 1 and negative values correspond to data 0. Note that, since the signals <i>s</i><sub>0</sub> and <i>s</i><sub>1</sub> include the noise <i>n</i>, the noise component cancels out. The data bit SNR is calculated as 20 log<sub>10</sub>(<i>e</i><sub>1</sub> / <i>e</i><sub>0</sub>). If the driver has not synchronized to the minute pulse, or if the data bit amplitude <i>e</i><sub>1</sub> or SNR are below thresholds, the bit is considered invalid and the bipolar signal is forced to zero.</p>
                <p>The bipolar signal is exponentially averaged in a set of 60 accumulators, one for each second, to determine the semi-static miscellaneous bits, such as DST indicator, leap second warning and DUT1 correction. In this design a data average value larger than a positive threshold is interpreted as +1 (hit) and a value smaller than a negative threshold as a -1 (miss). Values between the two thresholds, which can occur due to signal fades, are interpreted as an erasure and result in no change of indication.</p>
                <h4>Maximum-Likelihood Decoder</h4>
-               <p>The BCD digit in each digit position of the timecode is represented as four data bits. The bits are correlated with the bits corresponding to each of the valid decimal digits in this position. If any of the four bits are invalid, the correlated value for all digits in this position is assumed zero. In either case, the values for all digits are exponentially averaged in a likelihood vector associated with this position. The digit associated with the maximum over all averaged values then becomes the maximum-likelihood selection for this position and the ratio of the maximum over the next lower value represents the digit SNR.</p>
+               <p>The BCD digit in each digit position of the timecode is represented as four data bits. The bits are correlated with the bits corresponding to each of the valid decimal digits in this position. If any of the four bits are invalid, the correlated value for all digits in this position is assumed zero. In either case, the values for all digits are exponentially averaged in a likelihood vector associated with this position. The digit associated with the maximum over all averaged values then becomes the maximum-likelihood candidate for this position and the ratio of the maximum over the next lower value represents the digit SNR.</p>
                <p>The decoding matrix contains nine row vectors, one for each digit position. Each row vector includes the maximum-likelihood digit, likelihood vector and other related data. The maximum-likelihood digit for each of the nine digit positions becomes the maximum-likelihood time of the century. A built-in transition function implements a conventional clock with decimal digits that count the minutes, hours, days and years, as corrected for leap seconds and leap years. The counting operation also rotates the likelihood vector corresponding to each digit as it advances. Thus, once the clock is set, each clock digit should correspond to the maximum-likelihood digit as transmitted.</p>
                <p>Each row of the decoding matrix also includes a compare counter and the most recently determined maximum-likelihood digit. If a digit likelihood exceeds the decision level and compares with previous digits for a number of successive minutes in any row, the maximum-likelihood digit replaces the clock digit in that row. When this condition is true for all rows and the second epoch has been reliably determined, the clock is set (or verified if it has already been set) and delivers correct time to the integral second. The fraction within the second is derived from the logical master clock, which runs at 8000 Hz and drives all system timing functions.</p>
                <h4>Master Clock Discipline</h4>
-               <p>The logical master clock is derived from the audio codec clock. Its frequency is disciplined by a frequency-lock loop (FLL) which operates independently of the data recovery functions. At averaging intervals determined by the measured jitter, the frequency error is calculated as the difference between the most recent and the current second epoch divided by the interval. The sample clock frequency is then corrected by this amount. When first started, the frequency averaging interval is eight seconds, in order to compensate for intrinsic codec clock frequency offsets up to 125 PPM. Under most conditions, the averaging interval doubles in stages from the initial value to over 1000 seconds, which results in an ultimate frequency precision of 0.125 PPM, or about 11 ms/day.</p>
-               <p>It is important that the logical clock frequency is stable and accurately determined, since in most applications the shortwave radio will be tuned to a fixed frequency where WWV or WWVH signals are not available throughout the day. In addition, in some parts of the US, especially on the west coast, signals from either or both WWV and WWVH may be available at different times or even at the same time. Since the propagation times from either station are almost always different, each station must be reliably identified before attempting to set the clock.</p>
-               <p>Reliable station identification requires accurate discrimination between very weak signals in noise and noise alone. The driver very aggressively soaks up every scrap of signal information, but has to be careful to avoid making pseudo-sense of noise alone. The signal quality metric depends on the minute pulse amplitude and SNR measured in second 0 of the minute, together with the data subcarrier amplitude and SNR measured in second 1. If all four values are above defined thresholds a hit is declared, otherwise a miss. The number of hits declared in the last six minutes by each station represents the high order bits of the metric value, while the current minute pulse amplitude represents the low order bits. The resulting value is then scaled from zero to 100 for use as a quality indicator. It is used by the autotune function described below and reported in the timecode string.</p>
+               <p>The logical master clock is derived from the audio codec clock. Its frequency is disciplined by a frequency-lock loop (FLL) which operates independently of the data recovery functions. The maximum value of the 5-ms pulse after the comb filter represents the on-time epoch of the second. At averaging intervals determined by the measured jitter, the frequency error is calculated as the difference between the epoches over the interval divided by the interval. The sample clock frequency is then corrected by this amount divided by a time constant of three.</p>
+               <p>When first started, the frequency averaging interval is eight seconds, in order to compensate for intrinsic codec clock frequency offsets up to 125 PPM. Under most conditions, the averaging interval doubles in stages from the initial value to 1024 s, which results in an ultimate frequency resolution of 0.125 PPM, or about 11 ms/day.</p>
+               <p>The data demodulation functions operate using the subcarrier clock, which is independent of the epoch. However, the data decoding functions are driven by the epoch. The decoder is phase-locked to the epoch in such a way that, when the clock state machine has reliably decoded the broadcast time to the second, the epoch timestamp of that second becomes a candidate to set the system clock.</p>
+               <p>The comb filter can have a long memory and is vulnerable to noise and stale data, especially when coming up after a long fade. Therefore, a candidate is considered valid only if the 5-ms signal amplitude and SNR&nbsp;are above thresholds. In addition, the system clock is not set until after one complete averaging interval has passed with valid candidates.</p>
+               <h4>Station Identification</h4>
+               <p>It is important that the logical clock frequency is stable and accurately determined, since in many applications the shortwave radio will be tuned to a fixed frequency where WWV or WWVH signals are not available throughout the day. In addition, in some parts of the US, especially on the west coast, signals from either or both WWV and WWVH may be available at different times or even at the same time. Since the propagation times from either station are almost always different, each station must be reliably identified before attempting to set the clock.</p>
+               <p>Reliable station identification requires accurate discrimination between very weak signals in noise and noise alone. The driver very aggressively soaks up every scrap of signal information, but has to be careful to avoid making pseudo-sense of noise alone. The signal quality metric depends on the minute pulse amplitude and SNR measured in second 0 of the minute, together with the data subcarrier amplitude and SNR measured in second 1. If all four values are above defined thresholds a hit is declared, otherwise a miss. In principle, the data pulse in second 58 is usable, but the AGC in most radios is not fast enough for a reliable measurement.</p>
+               <p>The number of hits declared in the last six minutes for each station represents the high order bits of the metric, while the current minute pulse amplitude represents the low order bits. Only if the metric is above a defined threshold is the station signal considered acceptable. The metric is also used by the autotune function described below and reported in the timecode string.</p>
                <h4>Performance</h4>
-               <p>It is the intent of the design that the accuracy and stability of the indicated time be limited only by the characteristics of the ionospheric propagation medium. Conventional wisdom is that manual synchronization via oscilloscope and HF medium is good only to a millisecond under the best propagation conditions.</p>
-               <p>The performance of the NTP daemon disciplined by this driver is clearly better than this, even under marginal conditions. The figure below shows the measured offsets over a typical day near the bottom of the sunspot cycle ending in October, 2006. Variations up to &plusmn;0.4 ms can be expected due to changing ionospheric layer height and ray geometry over the day and night.</p>
+               <p>It is the intent of the design that the accuracy and stability of the indicated time be limited only by the characteristics of the ionospheric propagation medium. Conventional wisdom is that manual synchronization via oscilloscope and HF medium is good only to a millisecond under the best propagation conditions. The performance of the NTP daemon disciplined by this driver is clearly better than this, even under marginal conditions.</p>
+               <p>The figure below shows the measured offsets over a typical day near the bottom of the sunspot cycle ending in October, 2006. Variations up to &plusmn;0.4 ms can be expected due to changing ionospheric layer height and ray geometry over the day and night.</p>
                <div align="center">
                        <img src="../pic/offset1211.gif" alt="gif"></div>
-               <p>The accuracy with this driver has been determined for a Pentium 4 running FreeBSD 6.1. For these measurements the computer clock was disciplined within a few microseconds of UTC using a PPS signal and GPS receiver and the measured offsets determined from the peerstats data.</p>
-               <p>The predicted propagation delay from the WWV transmitter at Boulder, CO, to the receiver at Newark, DE, varies over 9.0-9.3 ms. In addition, the receiver contributes 4.7 ms, codec 0.2 ms and 600-Hz bandpass filter 1.1 ms. With these values, the systematic error, which can be eliminated by the <tt>fudge time1</tt> parameter, is about 0.4 ms and varies &plusmn;0.4 ms over the day as the result of changing ionospheric height and ray geometry.</p>
-               <h4>Program Operation</h4>The driver begins operation immediately upon startup. It first searches for one or both of the stations WWV and WWVH and attempts to acquire minute synch. This may take some fits and starts, as the driver expects to see several consecutive minutes with good signals and low jitter. If the autotune function is active, the driver will rotate over all five frequencies and both WWV and WWVH stations until finding a station and frequency with acceptable metric.<p>When a minute synch candidate has been found, the driver acquires second synch, which can take up to several minutes, depending on signal quality. At the same time the driver accumulates likelihood values for the unit (seconds) digit of the nine timecode digits, plus the seven miscellaneous bits included in the WWV/H transmission format. When a good unit digit has been found, the driver accumulated likelihood values for the remaining eight digits of the timecode. When three repetitions of all nine digits have decoded correctly, which normally takes 15 minutes with good signals, and up to 40 minutes when buried in noise, and the second synch has been acquired, the clock is set (or verified) and is selectable to discipline the system clock.</p>
-               <p>Once the clock is set, it continues to provide correct timecodes, even if all signals are lost. The time is considered correct as long as the second synch amplitude and SNR are above specified thresholds and jitter is below threshold. As long as the clock is set or verified, the system clock offsets are provided once each minute to the reference clock interface, where they are processed using the same algorithms used with other reference clocks and remote servers. Using these algorithms, the system clock can in principle be disciplined to a much finer resolution than the 125-<font face="Symbol">m</font>s sample interval would suggest, although the ultimate accuracy is probably limited by propagation delay variations as the ionospheric height varies throughout the day and night.</p>
-               <p>The codec clock frequency is disciplined during times when WWV/H signals are available. The algorithm refines the frequency offset using increasingly longer averaging intervals to 1024 s, where the precision is about 0.1 PPM. With good signals, it takes well over two hours to reach this degree of precision; however, it can take many more hours than this in case of marginal signals. Once reaching the limit, the algorithm will follow frequency variations due to temperature fluctuations and ionospheric height variations.</p>
+               <p>The figure was constructed using a 2.4-GHz P4 running FreeBSD 6.1. For these measurements the computer clock was disciplined within a few microseconds of UTC using a PPS signal and GPS receiver and the measured offsets determined from the filegen peerstats data.</p>
+               <p>The predicted propagation delay from the WWV transmitter at Boulder, CO, to the receiver at Newark, DE, varies over 9.0-9.3 ms. In addition, the receiver contributes 4.7 ms and the 600-Hz bandpass filter 0.9 ms. With these values, the mean error is less than 0.1 ms and varies &plusmn;0.3 ms over the day as the result of changing ionospheric height and ray geometry.</p>
+               <h4>Program Operation</h4>
+               The driver begins operation immediately upon startup. It first searches for one or both of the stations WWV and WWVH and attempts to acquire minute synch. This may take some fits and starts, as the driver expects to see several consecutive minutes with good signals and low jitter. If the autotune function is active, the driver will rotate over all five frequencies and both WWV and WWVH stations until finding a station and frequency with acceptable metric.
+               <p>While this is going on the the driver acquires second synch, which can take up to several minutes, depending on signal quality. When minute synch has been acquired, the driver accumulates likelihood values for the unit (seconds) digit of the nine timecode digits, plus the seven miscellaneous bits included in the WWV/H transmission format. When a good unit digit has been found, the driver accumulated likelihood values for the remaining eight digits of the timecode. When three repetitions of all nine digits have decoded correctly, which normally takes 15 minutes with good signals, and up to 40 minutes when buried in noise, and the second synch has been acquired, the clock is set (or verified) and is selectable to discipline the system clock.</p>
+               <p>Once the clock is set, it continues to provide correct timecodes as long as the signal metric is above threshold, as described in the previous section. As long as the clock is correctly set or verified, the system clock offsets are provided once each minute to the reference clock interface, where they are processed using the same algorithms as with other reference clocks and remote servers.</p>
                <p>It may happen as the hours progress around the clock that WWV and WWVH signals may appear alone, together or not at all. When the driver has mitigated which station and frequency is best, it sets the reference identifier to the string WV<i>f</i> for WWV and WH<i>f</i> for WWVH, where <i>f</i> is the frequency in megahertz. If the propagation delays have been properly set with the <tt>fudge time1</tt> (WWV) and <tt>fudge time2</tt> (WWVH) commands in the configuration file, handover from one station to the other is seamless.</p>
-               <p>Once the clock has been set for the first time, it will appear reachable and selectable to discipline the system clock. Operation continues as long as the signal quality from at least one station on at least one frequency is acceptable. A consequence of this design is that, once the clock is set, the time and frequency are disciplined only by the second synch pulse and the clock digits themselves are driven by the clock state machine. If for some reason the state machine drifts to the wrong second, it would never resynchronize. To protect against this most unlikely situation, if after two days with no signals, the clock is considered unset and resumes the synchronization procedure from the beginning.</p>
-               <p>However, as long as the clock has once been set correctly and allowed to converge to the intrinsic codec clock frequency, it will continue to read correctly even during the holdover interval, but with increasing dispersion. Assuming the clock frequency can be disciplined within 1 PPM, it can coast without signals for several days without exceeding the NTP step threshold of 128 ms. During such periods the root distance increases at 15 <font face="Symbol">m</font>s per second, which makes the driver appear less likely for selection as time goes on. Eventually, when the distance due all causes exceeds 1 s, it is no longer suitable for synchronization. Ordinarily, this  happens after about 18 hours with no signals. The <tt>tinker maxdist</tt> configuration command can be used to change this value.</p>
-               <p>To work well, the driver needs a shortwave receiver with good audio response at 100 Hz. Most shortwave and communications receivers roll off the audio response below 250 Hz, so this can be a problem, especially with receivers using DSP technology, since DSP filters can have very fast rolloff outside the passband. Some DSP transceivers, in particular the ICOM 775, have a programmable low frequency cutoff which can be set as low as 80 Hz. However, this particular radio has a strong low frequency buzz at about 10 Hz which appears in the audio output and can affect data recovery under marginal conditions. Although not tested, it would seem very likely that a cheap shortwave receiver could function just as well as an expensive communications receiver.</p>
+               <p>Operation continues as long as the signal metric from at least one station on at least one frequency is acceptable. A consequence of this design is that, once the clock is set, the time and frequency are disciplined only by the second synch pulse and the clock digits themselves are driven by the clock state machine. If for some reason the state machine drifts to the wrong second, it would never resynchronize. To protect against this most unlikely situation, if after two days with no signals, the clock is considered unset and resumes the synchronization procedure from the beginning.</p>
+               <p>Once the system clock been set correctly it will continue to read correctly even during the holdover interval, but with increasing dispersion. Assuming the system clock frequency can be disciplined within 1 PPM, it can coast without signals for several days without exceeding the NTP step threshold of 128 ms. During such periods the root distance increases at 15 <font face="Symbol">m</font>s per second, which makes the driver appear less likely for selection as time goes on. Eventually, when the distance due all causes exceeds 1 s, it is no longer suitable for synchronization. Ordinarily, this  happens after about 18 hours with no signals. The <tt>tinker maxdist</tt> configuration command can be used to change this value.</p>
                <h4>Autotune</h4>
                <p>The driver includes provisions to automatically tune the radio in response to changing radio propagation conditions throughout the day and night. The radio interface is compatible with the ICOM CI-V standard, which is a bidirectional serial bus operating at TTL levels. The bus can be connected to a standard serial port using a level converter such as the CT-17. Further details are on the <a href="../audio.html">Reference Clock Audio Drivers</a> page.</p>
                <p>If specified, the driver will attempt to open the device <tt>/dev/icom</tt> and, if successful will activate the autotune function and tune the radio to each operating frequency in turn while attempting to acquire minute synch from either WWV or WWVH. However, the driver is liberal in what it assumes of the configuration. If the <tt>/dev/icom</tt> link is not present or the open fails or the CI-V bus is inoperative, the driver quietly gives up with no harm done.</p>
-               <p>Once acquiring minute synch, the driver operates as described above to set the clock. However, during seconds 59, 0 and 1 of each minute it tunes the radio to one of the five broadcast frequencies to measure the minute synch pulse amplitude and SNR in second 0 and data pulse amplitude and SNR in second 1 to update the signal metric. In principle, the data pulse in second 58 is usable, but the AGC in most radios is not fast enough for a reliable measurement. Each of the five frequencies are probed in a five-minute rotation to build a database of current propagation conditions for all signals that can be heard at the time. At the end of each probe a mitigation procedure scans the database and retunes the radio to the best frequency and station found. For this to work well, the radio should be set for a fast AGC recovery time. This is most important while tracking a strong signal, which is normally the case, and then probing another frequency, which may have much weaker signals.</p>
-               <p>At the end of each probe, the frequency and station with the maximum metric is chosen, with ties going first to the highest frequency and then to WWV in order. A station is considered valid only if the metric is above a specified threshold; if below, the rotating probes continue until a valid station is found.</p>
+               <p>Once acquiring minute synch, the driver operates as described above to set the clock. However, during seconds 59, 0 and 1 of each minute it tunes the radio to one of the five broadcast frequencies to measure the signal metric as descrobed above. Each of the five frequencies are probed in a five-minute rotation to build a database of current propagation conditions for all signals that can be heard at the time. At the end of each probe a mitigation procedure scans the database and retunes the radio to the best frequency and station found. For this to work well, the radio should be set for a fast AGC recovery time. This is most important while tracking a strong signal, which is normally the case, and then probing another frequency, which may have much weaker signals.</p>
+               <p>The mitigation procedure selects the frequency and station with the highest valid metric, ties going first to the highest frequency and then to WWV in order. A station is considered valid only if the metric is above a specified threshold; if no station is above the metric, the rotating probes continue until a valid station is found.</p>
                <p>The behavior of the autotune function over a typical day is shown in the figure below.</p>
                <div align="center">
                        <img src="../pic/freq1211.gif" alt="gif"></div>
                <p>As expected, the lower frequencies prevail when the ray path is in moonlight (0100-1300 UTC) and the higher frequencies when the path is in sunlight (1300-0100 UTC). Note two periods in the figure show zero frequency when signals are below the minimum for all frequencies and stations.</p>
-               <h4>Diagnostics</h4>
+               <h4>Debugging Aids</h4>
+               <p>The most convenient way to track the driver status is using the <tt>ntpq</tt> program and the <tt>clockvar</tt> command. This displays the last determined timecode and related status and error counters, even when the driver is not disciplining the system clock. If the debugging trace feature (<tt>-d</tt> on the <tt>ntpd</tt> command line) is enabled, the driver produces detailed status messages as it operates. If the <tt>fudge flag 4</tt> is set, these messages are written to the <tt>clockstats</tt> file. All messages produced by this driver have the prefix <tt>wwv</tt> for convenient filtering with the Unix <tt>grep</tt> command.</p>
                <p>The autotune process produces diagnostic information along with the timecode. This is very useful for evaluating the performance of the algorithms, as well as radio propagation conditions in general. The message is produced once each minute for each frequency in turn after minute synch has been acquired.</p>
                <p><tt>wwv5 status agc epoch secamp/secsnr datamp/datsnr wwv wwvh</tt></p>
                <p>where the fields after the <tt>wwv5</tt> identifier are: <tt>status</tt> contains status bits, <tt>agc</tt> audio gain, <tt>epoch </tt>second epoch, <tt>secamp/secsnr </tt>second pulse amplitude/SNR, and <tt>wwv</tt> and <tt>wwvh</tt> are two sets of fields, one each for WWV and WWVH. Each of the two fields has the format</p>
                <p>where <tt>ident </tt>encodes the station (<tt>WV</tt> for WWV, <tt>WH</tt> for WWVH) and frequency (2, 5, 10, 15 or 20), <tt>score</tt> 32-bit shift register recording the hits (1) and misses (0) of the last 32 probes (hits and misses enter from the right), <tt>metric</tt> is described above, and <tt>minamp/minsnr</tt> is the minute pulse ampliture/SNR. An example is:</p>
                <pre><tt>wwv5 000d 111 5753 3967/20.1 3523/10.2 WV20 bdeff 100 8348/30.0 WH20 0000 1 22/-12.4</tt></pre>
                <p>There are several other messages that can occur; these are documented in the source listing.</p>
-               <h4>Debugging Aids</h4>
-               <p>The most convenient way to track the driver status is using the <tt>ntpq</tt> program and the <tt>clockvar</tt> command. This displays the last determined timecode and related status and error counters, even when the driver is not disciplining the system clock. If the debugging trace feature (<tt>-d</tt> on the <tt>ntpd</tt> command line) is enabled, the driver produces detailed status messages as it operates. If the <tt>fudge flag 4</tt> is set, these messages are written to the <tt>clockstats</tt> file. All messages produced by this driver have the prefix <tt>wwv</tt> for convenient filtering with the Unix <tt>grep</tt> command.</p>
                <h4>Monitor Data</h4>
                
+               
                When enabled by the <tt>filegen</tt> facility, every received timecode is written to the <tt>clockstats</tt> file in the following format:
                <p><tt>sq yyyy ddd hh:mm:ss l d du lset agc ident metric errs freq avg<br>
                        </tt></p>
index d00407b35ce9507ab345252e14803e54786b498c..bc514b9caa8c3f6fddca3a9887e6c9569272db17 100644 (file)
                        Driver ID: <tt>IRIG_AUDIO</tt><br>
                        Audio Device: <tt>/dev/audio</tt> and <tt>/dev/audioctl</tt>
                <h4>Description</h4>
-               <p>This driver supports the Inter-Range Instrumentation Group (IRIG) standard time distribution signal using the audio codec native to most workstations and PCs. This signal is generated by several radio clocks, including those made by Arbiter, Austron, Bancomm, Odetics, Spectracom, Symmetricom and TrueTime, among others, although it is often an add-on option. The signal is connected via an optional attenuator and cable to either the microphone or line-in port. The driver receives, demodulates and decodes the IRIG-B and IRIG-E signal formats using internal filters designed to reduce the effects of noise and interference.</p>
-               <p>In general and without calibration, the driver is accurate within 500 <font face="symbol">m</font>s relative to the IRIG time. When calibrated against a PPS&nbsp;signal from a GPS&nbsp;receiver, the mean error can be reduced to less than 20 <font face="symbol">m</font>s with standard deviation 10 <font face="symbol">m</font>s. Most of this is due to residuals after filtering and averaging the raw codec samples, which have an inherent jitter of 125 <font face="symbol">m</font>s.</p>
-               <p>The driver performs a number of error checks to protect against overdriven or underdriven input signal levels, incorrect signal format or improper hardware configuration. The specific checks are detailed later in this page. Note that additional checks are done elsewhere in the reference clock interface routines. In order to assure reliable signal capture, the codec frequency error must be less than 250 PPM (.025 percent). The <tt>tinker codec</tt> configuration command can be used to bracket the codec frequency to this range.</p>
+               <p>This driver synchronizes the computer time using the Inter-Range Instrumentation Group (IRIG) standard time distribution signal. This signal is generated by several radio clocks, including those made by Arbiter, Austron, Bancomm, Odetics, Spectracom, Symmetricom and TrueTime, among others, although it is often an add-on option. The signal is connected via an optional attenuator and cable to either the microphone or line-in port of a workstation or PC.</p>
+               <p>The driver requires an audio codec or sound card with sampling rate 8 kHz and <font face="symbol">m</font>-law companding to demodulate the data. This is the same standard as used by the telephone industry and is supported by most hardware and operating systems, including Solaris, FreeBSD and Linux, among others. In this implementation, only one audio driver and codec can be supported on a single machine. In order to assure reliable signal capture, the codec frequency error must be less than 125 PPM (.0125 percent). If necessary, the <tt>tinker codec</tt> configuration command can be used to bracket the codec frequency to this range.</p>
+               <p>For proper operation the IRIG signal source should be configured for analog signal levels, not digital TTL levels. In most radios the IRIG signal is driven &plusmn;10 V behind 50 Ohms. In such cases the cable should be terminated at the line-in port with a 50-Ohm resistor to avoid overloading the codec. Where feasible, the IRIG signal source should be operated with signature control so that, if the signal is lost or mutilated, the source produces an unmodulated signal, rather than possibly random digits. The driver automatically rejects the data and declare itself unsynchronized in this case. Some devices, in particular Spectracom radio/satellite clocks, provide additional year and status indication; other devices may not.</p>
+               <p>In general and without calibration, the driver is accurate within 500 <font face="symbol">m</font>s relative to the IRIG time. After calibrating relative to the PPS&nbsp;signal from a GPS&nbsp;receiver, the mean offset with a 2.4-GHz P4 running FreeBSD 6.1 is less than 20 <font face="symbol">m</font>s with standard deviation 10 <font face="symbol">m</font>s. Most of this is due to residuals after filtering and averaging the raw codec samples, which have an inherent jitter of 125 <font face="symbol">m</font>s. The processor load due to the driver is 0.6 percent on the P4.</p>
+               <p>However, be acutely aware that the accuracy with Solaris 2.8 and beyond has been seriously degraded to the order of several milliseconds. The Sun kernel driver has a sawtooth modulation with amplitude over 5 ms P-P and period 5.5 s. This distortion is especially prevalent with Sun Blade 1000 and possibly other systems.</p>
+               <p>The driver performs a number of error checks to protect against overdriven or underdriven input signal levels, incorrect signal format or improper hardware configuration. The specific checks are detailed later in this page. Note that additional checks are done elsewhere in the reference clock interface routines.</p>
                <p>This driver incorporates several features in common with other audio drivers such as described in the <a href="driver7.html">Radio CHU Audio Demodulator/Decoder</a> and the <a href="driver36.html">Radio WWV/H Audio Demodulator/Decoder</a> pages. They include automatic gain control (AGC), selectable audio codec port and signal monitoring capabilities. For a discussion of these common features, as well as a guide to hookup, debugging and monitoring, see the <a href="../audio.html">Reference Clock Audio Drivers</a> page.</p>
-               <p>Unlike other drivers, which can have multiple instantiations, this one supports only one. It does not seem likely that more than one audio codec would be useful in a single machine. More than one would probably chew up too much CPU time anyway.</p>
-               <h4>Baseband Signal Processing</h4>
-               <p>The IRIG signal format uses an amplitude-modulated carrier with pulse-width modulated data bits. For IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. While IRIG-B provides the best accuracy, generally within a few tens of microseconds relative to IRIG time, it can also generate a significant load on the processor with older workstations. Generally, the accuracy with IRIG-E is about ten times worse than IRIG-B, but the processor load is somewhat less.</p>
-               <p>The driver processes 8000-Hz <font face="symbol">m</font>-law companded samples using separate signal filters for IRIG-B and IRIG-E, a comb filter, envelope detector and automatic threshold corrector. Infinite impulse response (IIR) filters are used with both IRIG-B and IRIG-E formats. A 1000-Hz bandpass filter is used for IRIG-B and a 130-Hz lowpass filter for IRIG-E. These are intended for use with noisy signals, such as might be received over a telephone line or radio circuit, or when interfering signals may be present in the audio passband. The driver determines which IRIG format is in use by sampling the amplitude of each filter output and selecting the one with maximum signal.</p>
-               <p>Cycle crossings relative to the corrected slice level determine the width of each pulse and its value - zero, one or position identifier. The data encode ten characters (20 BCD digits) which determine the second, minute, hour and day of the year and sometimes the year and synchronization condition. The comb filter exponentially averages the corresponding samples of successive baud intervals in order to reliably identify the reference carrier cycle.</p>
+               <h4>Technical Overview</h4>
+               <p>The IRIG signal format uses an amplitude-modulated carrier with pulse-width modulated data bits. For IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. While IRIG-B provides the best accuracy, generally within a few tens of microseconds relative to IRIG time, it can also generate a significant processor load with older workstations. Generally, the accuracy with IRIG-E is about ten times worse than IRIG-B, but the processor load is somewhat less. Technical details about the IRIG&nbsp;formats can be found in <a href="http://handle.dtic.mil/100.2/ADA346250">IRIG Standard 200-98</a>.</p>
+               <p>The driver processes 8000-Hz <font face="symbol">m</font>-law companded samples using separate signal filters for IRIG-B and IRIG-E, a comb filter, envelope detector and automatic threshold corrector. An infinite impulse response (IIR) 1000-Hz bandpass filter is used for IRIG-B and an IIR 130-Hz lowpass filter for IRIG-E. These are intended for use with noisy signals, such as might be received over a telephone line or radio circuit, or when interfering signals may be present in the audio passband. The driver determines which IRIG format is in use by sampling the amplitude of each filter output and selecting the one with maximum signal.</p>
+               <p>Cycle crossings relative to the corrected slice level determine the width of each pulse and its value - zero, one or position identifier (PI). The data encode ten characters (20 BCD digits) which determine the second, minute, hour and day of the year and with some IRIG&nbsp;generators the year and synchronization condition. The comb filter exponentially averages the corresponding samples of successive baud intervals in order to reliably identify the reference carrier cycle.</p>
                <p>A type-II phase-lock loop (PLL) performs additional integration and interpolation to accurately determine the zero crossing of that cycle, which determines the reference timestamp. A pulse-width discriminator demodulates the data pulses, which are then encoded as the BCD digits of the timecode. The timecode and reference timestamp are updated once each second with IRIG-B (ten seconds with IRIG-E) and local clock offset samples saved for later processing. At poll intervals of 64 s, the saved samples are processed by a median filter and used to update the system clock.</p>
-               <h4>IRIG-B/E Timecode Format</h4>
-               <p>The 100 elements of the IRIG timecode are numbered from 0 through 99. Position identifiers occur at elements 0, 9 and every ten thereafter to 99. The control function (CF) elements begin at element 50 (CF 1) and extend to element 78 (CF 27). The straight-binary-seconds (SBS) field, which encodes the seconds of the UTC day, begins at element 80 (CF 28) and extends to element 97 (CF 44). The encoding of elements 50 (CF 1) through 78 (CF 27) is device dependent. This driver presently decodes the CF elements, but does nothing with them.</p>
-               <p>Where feasible, the IRIG signal source should be operated with signature control so that, if the signal is lost or mutilated, the source produces an unmodulated signal, rather than possibly random digits. The driver will automatically reject the data and declare itself unsynchronized in this case. Some devices, in particular Spectracom radio/satellite clocks, provide additional year and status indication in the format:</p>
-               <pre>
-     Element   CF        Function
-     -------------------------------------
-     55        6         time sync status
-     60-63     10-13     BCD year units
-     65-68     15-18     BCD year tens
-</pre>
-               Other devices set these elements to zero.
-               <h4>Performance and Horror Stories</h4>
-               <p>The <font face="symbol">m</font>-law companded data format allows considerable latitude in signal levels; however, an automatic gain control (AGC) function is implemented to further compensate for varying input signal levels and to avoid signal distortion. For proper operation, the IRIG signal source should be configured for analog signal levels, NOT digital TTL levels. In most radios the IRIG signal is driven &plusmn;10 V behind 50 Ohms. In such cases the cable should be terminate at the line-in port with a 50-Ohm resistor to avoid overloading the codec.</p>
-               <p>The accuracy with this driver has been determined for a Pentium 4 running FreeBSD 6.1. For these measurements the computer clock was disciplined within a few microseconds of UTC using a PPS signal and GPS receiver and the measured offsets determined from the peerstats data. The systematic error with AC97 codec is within 20 <font face="symbol">m</font>s of nominal zero with standard deviation about 20 <font face="symbol">m</font>s and maximum deviation 30 <font face="symbol">m</font>s.</p>
-               <p>However, be acutely aware that the accuracy with Solaris 2.8 and presumably beyond has been seriously degraded to the order of several milliseconds. The Sun kernel driver has a sawtooth modulation with amplitude over 5 ms P-P and period 5.5 s. This distortion is especially prevalent with Sun Blade 1000 and possibly other systems.</p>
-               <p>The processor resources consumed by the daemon can be significant, ranging from about 1.2 percent on the faster UltraSPARC II to 38 percent on the slower SPARC IPC. However, the overall timing accuracy is limited by the resolution and stability of the CPU clock oscillator and the interval between clock corrections, which is 64 s with this driver. This performance, while probably the best that can be achieved by the daemon itself, can be improved with assist from the PPS discipline as described elsewhere in this documentation.</p>
                <h4>Monitor Data</h4>
+               
+               
                The timecode format used for debugging and data recording includes data helpful in diagnosing problems with the IRIG signal and codec connections. With debugging enabled (-d on the ntpd command line), the driver produces one line for each timecode in the following format:
                <p><tt>00 1 98 23 19:26:52 721 143 0.694 20 0.3 66.5 3094572411.00027</tt></p>
                <p>The first field containes the error flags in hex, where the hex bits are interpreted as below. This is followed by the IRIG status indicator, year of century, day of year and time of day. Note that the time of day is for the previous minute, not the current time. The status indicator and year are not produced by some IRIG devices and appear as zeros. Following these fields are the carrier amplitude (0-6000), codec gain (0-255), modulation index (0-1), time constant (4-20), carrier phase error (0&plusmn;0.5) and carrier frequency error (PPM). The last field is the on-time timestamp in NTP format.</p>
index b6d0d5c876a225d3511a2ecf7a034fe34c370ec5..068741fc632c1b73ec3b96004d0ff83bb3a80f01 100644 (file)
                        Autotune Port: <tt>/dev/icom</tt>; 1200/9600 baud, 8-bits, no parity<br>
                        Audio Device: <tt>/dev/audio</tt> and <tt>/dev/audioctl</tt>
                <h4>Description</h4>
-               <p>This driver synchronizes the computer time using data encoded in radio transmissions from Canadian time/frequency station CHU in Ottawa, Ontario. It replaces an earlier driver built by Dennis Ferguson in 1988, which required a special line discipline to preprocessed the signal. The new driver includes more powerful algorithms implemented directly in the driver and requires no preprocessing.</p>
-               <p>CHU transmissions are made continuously on 3.330 MHz, 7.335 MHz and 14.670 MHz in upper sideband, compatible AM mode. An ordinary shortwave receiver can be tuned manually to one of these frequencies or, in the case of ICOM receivers, the receiver can be tuned automatically as propagation conditions change throughout the day and night.</p>
-               <p>In general and without calibration, the driver is accurate within 1 ms relative to the broadcast time when tracking a station. However, variations up to 0.5 ms can be expected due to diurnal variations in ionospheric layer height. In Newark DE, 625 km from the transmitter, the predicted one-hop propagation delay varies from 2.8 ms in sunlight to 2.6 ms in moonlight. When not tracking the station the accuracy depends on the computer clock oscillator stability, ordinarily better than 0.5 PPM.</p>
-               <p>While there are currently no known commercial CHU receivers, a simple but effective receiver/demodulator can be constructed from an ordinary shortwave receiver and Bell 103 compatible, 300-b/s modem or modem chip, as described on the <a href="../pps.html">Pulse-per-second (PPS) Signal Interfacing</a> page. This driver can use the modem to receive the radio signal and demodulate the data or, if available, the driver can use the audio codec native to most PCs and workstations today. In the latter case, the driver implements the modem using DSP routines, so the radio can be connected directly to either the microphone or line input port.</p>
+               <p>This driver synchronizes the computer time using shortwave radio transmissions from Canadian time/frequency station <a href="http://inms-ienm.nrc-cnrc.gc.ca/time_services/shortwave_broadcasts_e.html">CHU</a> in Ottawa, Ontario. CHU transmissions are made continuously on 3.330, 7.335 and 14.670 MHz in upper sideband, compatible AM mode. An ordinary shortwave receiver can be tuned manually to one of these frequencies or, in the case of ICOM receivers, the receiver can be tuned automatically as propagation conditions change throughout the day and season.</p>
+               <p>The driver can be compiled to use either an audio codec or soundcard, or a Bell 103-compatible, 300-b/s modem or modem chip, as described on the <a href="../pps.html">Pulse-per-second (PPS) Signal Interfacing</a> page. If compiled for a modem, the driver uses it to receive the radio signal and demodulate the data. If compiled for the audio codec, it requires a sampling rate of 8 kHz and <font face="symbol">m</font>-law companding to demodulate the data. This is the same standard as used by the telephone industry and is supported by most hardware and operating systems, including Solaris, FreeBSD and Linux, among others. The radio is connected via an optional attenuator and cable to either the microphone or line-in port of a workstation or PC. In this implementation, only one audio driver and codec can be supported on a single machine.</p>
+               <p>In general and without calibration, the driver is accurate within 1 ms relative to the broadcast time when tracking a station. However, variations up to 0.3 ms can be expected due to diurnal variations in ionospheric layer height and ray geometry. In Newark DE, 625 km from the transmitter, the predicted one-hop propagation delay varies from 2.8 ms in sunlight to 2.6 ms in moonlight. When not tracking the station the accuracy depends on the computer clock oscillator stability, ordinarily better than 0.5 PPM.</p>
+               <p>After calibration relative to the PPS&nbsp;signal from a GPS&nbsp;receiver, the mean offset with a 2.4-GHz P4 running FreeBSD 6.1 is generally within 0.2 ms short-term with 0.4 ms jitter. The long-term mean offset varies up to 0.3 ms due to propagation path geometry variations. The processor load due to the driver is 0.4 percent on the P4.</p>
                <p>The driver performs a number of error checks to protect against overdriven or underdriven input signal levels, incorrect signal format or improper hardware configuration. The specific checks are detailed later in this page. Note that additional checks are done elsewhere in the reference clock interface routines.</p>
                <p>This driver incorporates several features in common with other audio drivers such as described in the <a href="driver36.html">Radio WWV/H Audio Demodulator/Decoder</a> and the <a href="driver6.html">IRIG Audio Decoder</a> pages. They include automatic gain control (AGC), selectable audio codec port and signal monitoring capabilities. For a discussion of these common features, as well as a guide to hookup, debugging and monitoring, see the <a href="../audio.html">Reference Clock Audio Drivers</a> page.</p>
-               <p>Unlike other drivers, which can have multiple instantiations, this one supports only one. It does not seem likely that more than one audio codec would be useful in a single machine. More than one would probably chew up too much CPU time anyway.</p>
-               <h4>Overview</h4>
-               <p>The driver processes 8000-Hz <font face="symbol">m</font>-law companded samples from the shortwave radio using maximum-likelihood techniques which exploit the considerable degree of redundancy available in each broadcast message or burst. As described below, every character is sent twice and, in the case of format A bursts, the burst is sent eight times every minute. A format B burst is considered correct only if every character matches its repetition in the burst. For the eight format A bursts, a majority decoder requires more than half of the 16 repetitions for each digit decode to the same value. Every character in every burst provides an independent timestamp upon arrival with a potential total of 60 timestamps for each minute.</p>
-               <p>A timecode in the format described below is assembled when all bursts have been received in the minute. The timecode is considered valid and the clock set when at least one valid format B burst has been decoded and the majority decoder declares success. Once the driver has synchronized for the first time, it will appear reachable and selectable to discipline the system clock. It is normal on occasion to miss a minute or two due to signal fades or noise. If eight successive minutes are missed, the driver is considered unreachable and the system clock will free-wheel at the latest determined frequency offset. Since the signals are almost always available during some period of the day and the NTP clock discipline algorithms are designed to work well even with long intervals between updates, it is unlikely that the system clock will drift more than a few milliseconds during periods of signal loss.</p>
+               <h4>Technical Overview</h4>
+               <p>The driver processes 8-kHz <font face="symbol">m</font>-law companded codec samplesusing maximum-likelihood techniques which exploit the considerable degree of redundancy available in each broadcast message or burst. As described below, every character is sent twice and, in the case of format A bursts, the burst is sent eight times every minute. The single format B burst is considered correct only if every character matches its repetition in the burst. For the eight format A bursts, a majority decoder requires more than half of the 16 repetitions for each digit decode to the same value. Every character in every burst provides an independent timestamp upon arrival with a potential total of 60 timestamps for each minute.</p>
+               <p>The CHU timecode format is described on the <a href="http://inms-ienm.nrc-cnrc.gc.ca/time_services/chu_e.html">CHU website</a>. A timecode is assembled when all bursts have been received in each minute. The timecode is considered valid and the clock set when at least one valid format B burst has been decoded and the majority decoder declares success. Once the driver has synchronized for the first time, it will appear reachable and selectable to discipline the system clock. It is normal on occasion to miss a minute or two due to signal fades or noise. If eight successive minutes are missed, the driver is considered unreachable and the system clock will free-wheel at the latest determined frequency offset. Since the signals are almost always available during some period of the day and the NTP clock discipline algorithms are designed to work well even with long intervals between updates, it is unlikely that the system clock will drift more than a few milliseconds during periods of signal loss.</p>
                <h4>Baseband Signal Processing</h4>
-               <p>The program consists of four major parts: the DSP modem, maximum-likelihood UART, burst assembler and majority decoder. The DSP modem demodulates Bell 103 modem answer-frequency signals; that is, frequency-shift keyed (FSK) tones of 2225 Hz (mark) and 2025 Hz (space). It consists of a 500-Hz bandpass filter centered on 2125 Hz followed by a limiter/discriminator and raised-cosine lowpass filter optimized for the 300-b/s data rate.</p>
+               <p>The program consists of four major parts: the DSP modem, maximum-likelihood UART, burst assembler and majority decoder. The DSP modem demodulates Bell 103 modem answer-frequency signals; that is, frequency-shift keyed (FSK) tones of 2225 Hz (mark) and 2025 Hz (space). It consists of a 500-Hz bandpass filter centered on 2125 Hz followed by a limiter/discriminator and raised-cosine lowpass filter optimized for the 300-b/s data rate. </p>
                <p>The maximum likelihood UART is implemented using a set of eight 11-stage shift registers, one for each of eight phases of the 300-b/s bit clock. At each phase a new baseband signal from the DSP modem is shifted into the corresponding register and the maximum and minimum over all 11 samples computed. This establishes a span (difference) and slice level (average) over all 11 stages. For each stage, a signal level above the slice is a mark (1) and below that is a space (0). A quality metric is calculated for each register with respect to the slice level and the a-priori signal consisting of a start bit (space), eight arbitrary information bits and two stop bits (mark).</p>
                <p>The shift registers are processed in round-robin order as the phases of each bit arrive. At the end of each bit all eight phases are searched for valid framing bits, sufficient span and best metric. The best candidate found in this way represents the maximum-likelihood character. The process then continues for all ten characters in the burst.</p>
                <p>The burst assembler processes characters either from the maximum-likelihood UART or directly from the serial port as configured. A burst begins when a character is received and is processed after a timeout interval when no characters are received. If the interval between characters is greater than two characters, but less than the timeout interval, the burst is rejected as a runt and a new burst begun. As each character is received, a timestamp is captured and saved for later processing.</p>
-               <p>A valid burst consists of ten characters in two replicated five-character blocks, each block  representing ten 4-bit BCD digits. The format B blocks sent in second 31 contain the year and other information in ten digits. The eight format A blocks sent in seconds 32-39 contain the timecode in ten digits, the first of which is a framing code (6). The burst assembler must deal with cases where the first character of a format A burst is lost or is noise. This is done using the framing codes to correct the phase, either one character early or one character late.</p>
+               <p>A valid burst consists of ten characters in two replicated five-character blocks, each block representing ten 4-bit BCD digits. The format B blocks sent in second 31 contain the year and other information in ten digits. The eight format A blocks sent in seconds 32-39 contain the timecode in ten digits, the first of which is a framing code (6). The burst assembler must deal with cases where the first character of a format A burst is lost or is noise. This is done using the framing codes to correct the discrepancy, either one character early or one character late.</p>
                <p>The burst distance is incremented by one for each bit in the first block that matches the corresponding bit in the second block and decremented by one otherwise. In a format B burst the second block is bit-inverted relative to the first, so a perfect burst of five 8-bit characters has distance -40. In a format A burst the two blocks are identical, so a perfect burst has distance +40. Format B bursts must be perfect to be acceptable; however, format A bursts, which are further processed by the majority decoder, are acceptable if the distance is at least 28.</p>
                <h4>Majority Decoder</h4>
                <p>Each minute of transmission includes eight format A bursts containing two timecodes for each second from 32 through 39. The majority decoder uses a decoding matrix of ten rows, one for each digit position in the timecode, and 16 columns, one for each 4-bit code combination that might be decoded at that position. In order to use the character timestamps, it is necessary to reliably determine the second number of each burst. In a valid burst, the last digit of the two timecodes in the burst must match and the value must be in the range 2-9 and greater than in the previous burst.</p>
                <h4>Autotune</h4>
                <p>The driver includes provisions to automatically tune the radio in response to changing radio propagation conditions throughout the day and night. The radio interface is compatible with the ICOM CI-V standard, which is a bidirectional serial bus operating at TTL levels. The bus can be connected to a standard serial port using a level converter such as the CT-17. Further details are on the <a href="../audio.html">Reference Clock Audio Drivers</a> page.</p>
                <p>If specified, the driver will attempt to open the device <tt>/dev/icom</tt> and, if successful will tune the radio to 3.331 MHz. The 1-kHz offset is useful with a narrowband SSB&nbsp;filter where the passband includes the carrier and modem signals. However, the driver is liberal in what it assumes of the configuration. If the <tt>/dev/icom</tt> link is not present or the open fails or the CI-V bus is inoperative, the driver continues in single-frequency mode.</p>
-               <p>As long as no bursts are received, the driver cycles over the three frequencies in turn, one minute for each station. As long as bursts are received from one or more stations, the driver continues in a five-minute cycle. During the first four minutes it tunes to the station with the highest metric. During the last minute it tunes to each of the other two stations in turn in order to measure the metric.</p>
-               <h4>Radio Broadcast Format</h4>
-               <p>The burst data consist of five characters (ten hex digits) followed by a repeat of these characters. In format A, the characters are repeated in the same polarity; in format B, the characters are repeated in the opposite polarity.</p>
-               <p>Format A bursts are sent at seconds 32 through 39 of the minute in decimal digits</p>
-               <p><tt>6dddhhmmss6dddhhmmss</tt></p>
-               <p>The first ten digits encode a frame marker (<tt>6</tt>) followed by the day (<tt>ddd</tt>), hour (<tt>hh</tt>), minute (<tt>mm</tt>) and second (<tt>ss</tt>). Since format A bursts are sent during the third decade of seconds the tens digit of <tt>ss</tt> is always 3. The driver uses this to determine correct burst synchronization. These digits are then repeated with the same polarity.</p>
-               <p>Format B bursts are sent at second 31 of the minute in decimal digits</p>
-               <p><tt>xdyyyyttaaxdyyyyttaa</tt></p>
-               <p>The first ten digits encode a code (<tt>x</tt> described below) followed by the DUT1 (<tt>d</tt> in deciseconds), Gregorian year (<tt>yyyy</tt>), difference TAI - UTC (<tt>tt</tt>) and daylight time indicator (<tt>aa</tt>) peculiar to Canada. These digits are then repeated with inverted polarity.</p>
-               <p>The <tt>x</tt> is coded bit</p>
-               <dl>
-                       <dt><tt>1</tt>
-                       <dd>Sign of DUT (0 = +)
-                       <dt><tt>2</tt>
-                       <dd>Leap second warning. One second will be added at the end of the month.<dt><tt>4</tt>
-                       <dd>Leap second warning. One second will be subtracted at the end of the month. This is not likely to happen in our universe.<dt><tt>8</tt>
-                       <dd>Even parity bit for this digit.</dl>
-               <p>By design, the last stop bit of the last character in the burst coincides with 0.5 second. Since characters have 11 bits and are transmitted at 300 b/s, the last stop bit of the first character coincides with 0.5 - 9 * 11/300 = 170 ms. The driver adds 6.5 ms to account for nominal receiver and filter delays. The additional propagation delay is determined from the <tt>fudge time1</tt> variable.</p>
+               <p>As long as no bursts are received, the driver cycles over the three frequencies in turn, one minute for each station. When bursts are received from one or more stations, the driver operates in a five-minute cycle. During the first four minutes it tunes to the station with the highest metric. During the last minute it alternates between the other two stations in turn in order to measure the metric.</p>
                <h4>Debugging Aids</h4>
                <p>The most convenient way to track the program status is using the <tt>ntpq</tt> program and the <tt>clockvar</tt> command. This displays the last determined timecode and related status and error counters, even when the program is not discipline the system clock. If the debugging trace feature (<tt>-d</tt> on the <tt>ntpd</tt> command line) is enabled, the program produces detailed status messages as it operates. If the <tt>fudge flag 4</tt> is set, these messages are written to the <tt>clockstats</tt> file. All messages produced by this driver have the prefix <tt>chu</tt> for convenient filtering with the Unix <tt>grep</tt> command.</p>
                <p>With debugging enabled the driver produces messages in the following formats: A single message beginning with <tt>chuB</tt> is produced for each format B burst received in second 31, while eight messages beginning with <tt>chuA</tt> are produced for each format A burst received in seconds 32 through 39 of the minute. The first four fields are</p>
                                        <dt><tt>2</tt>
                                        <dd>Format alarm. One or more bursts contained invalid data or was improperly formatted.<dt><tt>1</tt>
                                        <dd>Frame alarm. One or more bursts was improperly framed or  contained too many repetition errors.</dl>
-                               <p>The timestamp and decoder alarms are fatal; the data accumulated during the minute is not used to set the clock. The format and fram alarm are nonfatal; only the data in the burst are discarded.</p>
+                               <p>The timestamp and decoder alarms are fatal; the data accumulated during the minute are not used to set the clock. The format and fram alarm are nonfatal; only the data in the burst are discarded.</p>
                        
                                
                        
index e96f9c6440758d47ac2ef6e2994828cb908cda6d..5a716d4ae7aace362a2e6350ea622fce4cda259c 100644 (file)
  * tuned automatically as propagation conditions change throughout the
  * day and season.
  *
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a suported workstation hardware and
- * operating system. These include Solaris, SunOS, FreeBSD, NetBSD and
- * Linux. In this implementation, only one audio driver and codec can be
- * supported on a single machine.
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
  *
  * The driver can be compiled to use a Bell 103 compatible modem or
  * modem chip to receive the radio signal and demodulate the data.
@@ -51,7 +52,7 @@
  * latter case, the driver implements the modem using DSP routines, so
  * the radio can be connected directly to either the microphone on line
  * input port. In either case, the driver decodes the data using a
- * maximum likelihood technique which exploits the considerable degree
+ * maximum-likelihood technique which exploits the considerable degree
  * of redundancy available to maximize accuracy and minimize errors.
  *
  * The CHU time broadcast includes an audio signal compatible with the
 #define BAUD           300     /* modulation rate (bps) */
 #define OFFSET         128     /* companded sample offset */
 #define SIZE           256     /* decompanding table size */
-#define        MAXSGL          6000.   /* maximum signal level */
+#define        MAXAMP          6000.   /* maximum signal level */
 #define        MAXCLP          100     /* max clips above reference per s */
 #define        SPAN            800.    /* min envelope span */
 #define LIMIT          1000.   /* soft limiter threshold */
 #define MINMETRIC      50      /* min channel metric (of 160) */
 
 /*
- * The offset to the last stop bit of the first character, which defines
- * the timecode offset 170 ms. To this is added the receiver delay 4.7
- * ms, codec delay 1 ms and modem delay 0.8 ms. The receiver delay was
- * measured, the codec delay came from the AC97 spec sheet and the modem
- * delay was measured in simulation. The result is within 0.5 ms as
- * verified by on-air testing. 
+ * The on-time synchronization point for the driver is the last stop bit
+ * of the first character 170 ms. The modem delay is 0.8 ms, while the
+ * receiver delay is approxmately 4.7 ms at 2125 Hz. The fudge value 1.3
+ * ms due to the codec and other causes was determined by calibrating to
+ * a PPS signal from a GPS receiver. The additional propagation delay
+ * specific to each receiver location can be programmed in the fudge
+ * time1. 
+ *
+ * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
+ * generally within 0.5 ms short term with 0.3 ms jitter. The long-term
+ * offsets vary up to 0.3 ms due to ionospheric layer height variations.
+ * The processor load due to the driver is 0.4 percent.
  */
-#define        FUDGE           .1765   /* offset to first stop bit (s) */
+#define        PDELAY  ((170 + .8 + 4.7 + 1.3) / 1000) /* system delay (s) */
 
 /*
  * Status bits (status)
 
 #ifdef HAVE_AUDIO
 /*
- * Maximum likelihood UART structure. There are eight of these
+ * Maximum-likelihood UART structure. There are eight of these
  * corresponding to the number of phases.
  */ 
 struct surv {
@@ -318,7 +325,7 @@ struct xmtr {
  * CHU unit control structure
  */
 struct chuunit {
-       u_char  decode[20][16]; /* maximum likelihood decoding matrix */
+       u_char  decode[20][16]; /* maximum-likelihood decoding matrix */
        l_fp    cstamp[BURST];  /* character timestamps */
        l_fp    tstamp[MAXSTAGE]; /* timestamp samples */
        l_fp    timestamp;      /* current buffer timestamp */
@@ -378,7 +385,7 @@ struct chuunit {
        int     discptr;        /* discriminator pointer */
 
        /*
-        * Maximum likelihood UART variables
+        * Maximum-likelihood UART variables
         */
        double  baud;           /* baud interval */
        struct surv surv[8];    /* UART survivor structures */
@@ -669,15 +676,15 @@ chu_audio_receive(
                sample = up->comp[~*dpt++ & 0xff];
 
                /*
-                * Clip noise spikes greater than MAXSgl. If no clips,
+                * Clip noise spikes greater than MAXAMP. If no clips,
                 * increase the gain a tad; if the clips are too high, 
                 * decrease a tad.
                 */
-               if (sample > MAXSGL) {
-                       sample = MAXSGL;
+               if (sample > MAXAMP) {
+                       sample = MAXAMP;
                        up->clipcnt++;
-               } else if (sample < -MAXSGL) {
-                       sample = -MAXSGL;
+               } else if (sample < -MAXAMP) {
+                       sample = -MAXAMP;
                        up->clipcnt++;
                }
                chu_rf(peer, sample);
@@ -711,7 +718,7 @@ chu_audio_receive(
  *
  * This routine implements a 300-baud Bell 103 modem with mark 2225 Hz
  * and space 2025 Hz. It uses a bandpass filter followed by a soft
- * limiter, FM discriminator and lowpass filter. A maximum likelihood
+ * limiter, FM discriminator and lowpass filter. A maximum-likelihood
  * decoder samples the baseband signal at eight times the baud rate and
  * detects the start bit of each character.
  *
@@ -822,7 +829,7 @@ chu_rf(
        lpf += up->lpf[0] = disc * 2.538771e-02;
 
        /*
-        * Maximum likelihood decoder. The UART updates each of the
+        * Maximum-likelihood decoder. The UART updates each of the
         * eight survivors and determines the span, slice level and
         * tentative decoded character. Valid 11-bit characters are
         * framed so that bit 10 and bit 11 (stop bits) are mark and bit
@@ -883,7 +890,7 @@ chu_rf(
 
 
 /*
- * chu_uart - maximum likelihood UART
+ * chu_uart - maximum-likelihood UART
  *
  * This routine updates a shift register holding the last 11 envelope
  * samples. It then computes the slice level and span over these samples
@@ -1368,7 +1375,7 @@ chu_second(
                        offset.l_uf = 0;
                        for (i = 0; i < up->ntstamp; i++)
                                refclock_process_offset(pp, offset,
-                                   up->tstamp[i], FUDGE +
+                               up->tstamp[i], PDELAY +
                                    pp->fudgetime1);
                        pp->lastref = up->timestamp;
                        refclock_receive(peer);
@@ -1606,11 +1613,12 @@ chu_dist(
 /*
  * chu_gain - adjust codec gain
  *
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
+ * This routine is called at the end of each second. During the second
+ * the number of signal clips above the MAXAMP threshold (6000). If
+ * there are no clips, the gain is bumped up; if there are more than
+ * MAXCLP clips (100), it is bumped down. The decoder is relatively
+ * insensitive to amplitude, so this crudity works just peachy. The
+ * routine also jiggles the input port and selectively mutes the
  */
 static void
 chu_gain(
index 2141f494d9197cc75b1811a6df86b9fbec6c90b5..aec811a51e2d114a2d6949ce84ce2069381dc111 100644 (file)
 /*
  * Audio IRIG-B/E demodulator/decoder
  *
- * This driver receives, demodulates and decodes IRIG-B/E signals when
- * connected to the audio codec /dev/audio. The IRIG signal format is an
- * amplitude-modulated carrier with pulse-width modulated data bits. For
- * IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for
- * IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. The
- * driver automatically recognizes which format is in use.
+ * This driver synchronizes the computer time using data encoded in
+ * IRIG-B/E signals commonly produced by GPS receivers and other timing
+ * devices. The IRIG signal is an amplitude-modulated carrier with
+ * pulse-width modulated data bits. For IRIG-B, the carrier frequency is
+ * 1000 Hz and bit rate 100 b/s; for IRIG-E, the carrier frequenchy is
+ * 100 Hz and bit rate 10 b/s. The driver automatically recognizes which
+ & format is in use.
+ *
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
  *
  * The program processes 8000-Hz mu-law companded samples using separate
  * signal filters for IRIG-B and IRIG-E, a comb filter, envelope
  * detector and automatic threshold corrector. Cycle crossings relative
  * to the corrected slice level determine the width of each pulse and
- * its value - zero, one or position identifier. The data encode 20 BCD
- * digits which determine the second, minute, hour and day of the year
- * and sometimes the year and synchronization condition. The comb filter
- * exponentially averages the corresponding samples of successive baud
- * intervals in order to reliably identify the reference carrier cycle.
- * A type-II phase-lock loop (PLL) performs additional integration and
- * interpolation to accurately determine the zero crossing of that
- * cycle, which determines the reference timestamp. A pulse-width
- * discriminator demodulates the data pulses, which are then encoded as
- * the BCD digits of the timecode.
+ * its value - zero, one or position identifier.
+ *
+ * The data encode 20 BCD digits which determine the second, minute,
+ * hour and day of the year and sometimes the year and synchronization
+ * condition. The comb filter exponentially averages the corresponding
+ * samples of successive baud intervals in order to reliably identify
+ * the reference carrier cycle. A type-II phase-lock loop (PLL) performs
+ * additional integration and interpolation to accurately determine the
+ * zero crossing of that cycle, which determines the reference
+ * timestamp. A pulse-width discriminator demodulates the data pulses,
+ * which are then encoded as the BCD digits of the timecode.
  *
  * The timecode and reference timestamp are updated once each second
  * with IRIG-B (ten seconds with IRIG-E) and local clock offset samples
 #define FIELD          100     /* bits per second */
 #define MINTC          2       /* min PLL time constant */
 #define MAXTC          20      /* max PLL time constant max */
-#define        MAXAMP          6000.   /* maximum signal level */
-#define        MAXCLP          100     /* max clips above reference per s */
-#define DRPOUT         100.    /* dropout signal level */
+#define        MAXAMP          5000.   /* maximum signal amplitude */
+#define        MINAMP          4000.   /* minimum signal amplitude */
+#define DRPOUT         100.    /* dropout signal amplitude */
 #define MODMIN         0.5     /* minimum modulation index */
 #define MAXFREQ                (250e-6 * SECOND) /* freq tolerance (.025%) */
 
 /*
- * The IIR baseband filter phase delay is 1.03 ms for IRIG-B and 3.47 ms
- * for IRIG-E. The AC97 codec delay is specified 1 ms at 44 kHz, but
- * must be more at 8 kHz. The value used here 1.81 ms was determined by
- * calibrating to a PPS signal from a GPS receiver.
+ * The on-time synchronization point is the positive-going zero crossing
+ * of the first cycle of the second. The IIR baseband filter phase delay
+ * is 1.03 ms for IRIG-B and 3.47 ms for IRIG-E. The fudge value 2.68 ms
+ * due to the codec and other causes was determined by calibrating to a
+ * PPS signal from a GPS receiver.
+ *
+ * The results with a 2.4-GHz P4 running FreeBSD 6.1 are generally
+ * within .02 ms short-term with .02 ms jitter. The processor load due
+ * to the driver is 0.51 percent.
  */
-#define IRIG_B         (.00103 + .00181) /* IRIG-B phase delay */
-#define IRIG_E         (.00347 + .00181) /* IRIG-E phase delay */
+#define IRIG_B ((1.03 + 2.68) / 1000)  /* IRIG-B system delay (s) */
+#define IRIG_E ((3.47 + 2.68) / 1000)  /* IRIG-E system delay (s) */
 
 /*
  * Data bit definitions
 #define IRIG_ERR_ERROR 0x40    /* codec error (overrun) */
 #define IRIG_ERR_SIGERR        0x80    /* IRIG status error (Spectracom) */
 
+static char    hexchar[] = "0123456789abcdef";
+
 /*
  * IRIG unit control structure
  */
@@ -204,7 +220,8 @@ struct irigunit {
        l_fp    timestamp;      /* audio sample timestamp */
        l_fp    tick;           /* audio sample increment */
        l_fp    refstamp;       /* reference timestamp */
-       l_fp    chrstamp;       /* character timestamp */
+       l_fp    chrstamp;       /* baud timestamp */
+       l_fp    prvstamp;       /* previous baud timestamp */
        double  integ[BAUD];    /* baud integrator */
        double  phase, freq;    /* logical clock phase and frequency */
        double  zxing;          /* phase detector integrator */
@@ -218,10 +235,10 @@ struct irigunit {
         * Audio codec variables
         */
        double  comp[SIZE];     /* decompanding table */
+       double  signal;         /* peak signal for AGC */
        int     port;           /* codec port */
        int     gain;           /* codec gain */
        int     mongain;        /* codec monitor gain */
-       int     clipcnt;        /* sample clipped count */
        int     seccnt;         /* second interval counter */
 
        /*
@@ -229,6 +246,8 @@ struct irigunit {
         */
        double  bpf[9];         /* IRIG-B filter shift register */
        double  lpf[5];         /* IRIG-E filter shift register */
+       double  envmin, envmax; /* envelope min and max */
+       double  slice;          /* envelope slice level */
        double  intmin, intmax; /* integrated envelope min and max */
        double  maxsignal;      /* integrated peak amplitude */
        double  noise;          /* integrated noise amplitude */
@@ -253,8 +272,9 @@ struct irigunit {
        int     dcycles;        /* data cycles */
        int     lastbit;        /* last code element */
        int     second;         /* previous second */
-       int     bitcnt;         /* bit count in character */
-       int     frmcnt;         /* frame count in second */
+       int     bitcnt;         /* bit count in frame */
+       int     frmcnt;         /* bit count in second */
+       int     xptr;           /* timecode pointer */
        int     bits;           /* demodulated bits */
 };
 
@@ -271,6 +291,7 @@ static      void    irig_poll       (int, struct peer *);
  */
 static void    irig_base       (struct peer *, double);
 static void    irig_rf         (struct peer *, double);
+static void    irig_baud       (struct peer *, int);
 static void    irig_decode     (struct peer *, int);
 static void    irig_gain       (struct peer *);
 
@@ -287,16 +308,6 @@ struct     refclock refclock_irig = {
        NOFLAGS                 /* not used */
 };
 
-/*
- * Global variables
- */
-static char    hexchar[] = {   /* really quick decoding table */
-       '0', '8', '4', 'c',     /* 0000 0001 0010 0011 */
-       '2', 'a', '6', 'e',     /* 0100 0101 0110 0111 */
-       '1', '9', '5', 'd',     /* 1000 1001 1010 1011 */
-       '3', 'b', '7', 'f'      /* 1100 1101 1110 1111 */
-};
-
 
 /*
  * irig_start - open the devices and initialize data for processing
@@ -435,19 +446,6 @@ irig_receive(
        for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
                sample = up->comp[~*dpt++ & 0xff];
 
-               /*
-                * Clip noise spikes greater than MAXAMP. If no clips,
-                * increase the gain a tad; if the clips are too high, 
-                * decrease a tad.
-                */
-               if (sample > MAXAMP) {
-                       sample = MAXAMP;
-                       up->clipcnt++;
-               } else if (sample < -MAXAMP) {
-                       sample = -MAXAMP;
-                       up->clipcnt++;
-               }
-
                /*
                 * Variable frequency oscillator. The codec oscillator
                 * runs at the nominal rate of 8000 samples per second,
@@ -468,6 +466,11 @@ irig_receive(
                        irig_rf(peer, sample);
                }
                L_ADD(&up->timestamp, &up->tick);
+               sample = fabs(sample);
+               if (sample > up->signal)
+                       up->signal = sample;
+                       up->signal += (sample - up->signal) /
+                           1000;
 
                /*
                 * Once each second, determine the IRIG format and gain.
@@ -481,8 +484,9 @@ irig_receive(
                                up->decim = 10;
                                up->fdelay = IRIG_E;
                        }
-                       irig_gain(peer);
                        up->irig_b = up->irig_e = 0;
+                       irig_gain(peer);
+
                }
        }
 
@@ -499,14 +503,14 @@ irig_receive(
                up->mongain = 0;
 }
 
+
 /*
  * irig_rf - RF processing
  *
  * This routine filters the RF signal using a bandass filter for IRIG-B
  * and a lowpass filter for IRIG-E. In case of IRIG-E, the samples are
- * decimated by a factor of ten. The lowpass filter functions also as a
- * decimation filter in this case. Note that the codec filters function
- * as roofing filters to attenuate both the high and low ends of the
+ * decimated by a factor of ten. Note that the codec filters function as
+ * roofing filters to attenuate both the high and low ends of the
  * passband. IIR filter coefficients were determined using Matlab Signal
  * Processing Toolkit.
  */
@@ -530,7 +534,7 @@ irig_rf(
        /*
         * IRIG-B filter. Matlab 4th-order IIR elliptic, 800-1200 Hz
         * bandpass, 0.3 dB passband ripple, -50 dB stopband ripple,
-        * phase delay 1.03 ms
+        * phase delay 1.03 ms.
         */
        irig_b = (up->bpf[8] = up->bpf[7]) * 6.505491e-001;
        irig_b += (up->bpf[7] = up->bpf[6]) * -3.875180e+000;
@@ -586,7 +590,8 @@ irig_rf(
  *
  * This routine processes the baseband signal and demodulates the AM
  * carrier using a synchronous detector. It then synchronizes to the
- * data frame at the baud rate and decodes the data pulses.
+ * data frame at the baud rate and decodes the width-modulated data
+ * pulses.
  */
 static void
 irig_base(
@@ -602,9 +607,8 @@ irig_base(
         */
        double  lope;           /* integrator output */
        double  env;            /* envelope detector output */
-       int     carphase;       /* carrier phase */
        double  dtemp;
-       l_fp    ltemp;
+       int     carphase;       /* carrier phase */
 
        pp = peer->procptr;
        up = (struct irigunit *)pp->unitptr;
@@ -612,8 +616,8 @@ irig_base(
        /*
         * Synchronous baud integrator. Corresponding samples of current
         * and past baud intervals are integrated to refine the envelope
-        * amplitude and phase estimate. We keep one cycle of both the
-        * raw and integrated data for later use.
+        * amplitude and phase estimate. We keep one cycle (1 ms) of the
+        * raw data and one baud (10 ms) of the integrated data.
         */
        up->envphase = (up->envphase + 1) % BAUD;
        up->integ[up->envphase] += (sample - up->integ[up->envphase]) /
@@ -624,17 +628,17 @@ irig_base(
        up->lastint[carphase] = lope;
 
        /*
-        * Phase detector. Sample amplitudes are integrated over the
-        * baud interval. Cycle phase is determined from these
-        * amplitudes using an eight-sample cyclic buffer. A phase
-        * change of 360 degrees produces an output change of one unit.
+        * Phase detector. Find the negative-going zero crossing
+        * relative to sample 4 in the 8-sample sycle. A phase change of
+        * 360 degrees produces an output change of one unit.
         */ 
        if (up->lastsig > 0 && lope <= 0)
                up->zxing += (double)(carphase - 4) / CYCLE;
        up->lastsig = lope;
 
        /*
-        * Update signal/noise estimates and PLL phase/frequency.
+        * End of the baud. Update signal/noise estimates and PLL
+        * phase, frequency and time constant.
         */
        if (up->envphase == 0) {
                up->maxsignal = up->intmax; up->noise = up->intmin;
@@ -677,17 +681,17 @@ irig_base(
 
        /*
         * Synchronous demodulator. There are eight samples in the cycle
-        * and ten cycles in the baud interval. The amplitude of each
-        * cycle is determined at the last sample in the cycle. The
+        * and ten cycles in the baud. Since the PLL has aligned the
+        * negative-going zero crossing at sample 4, the maximum
+        * amplitude is at sample 2 and minimum at sample 6. The
         * beginning of the data pulse is determined from the integrated
         * samples, while the end of the pulse is determined from the
         * raw samples. The raw data bits are demodulated relative to
         * the slice level and left-shifted in the decoding register.
         */
-       if (carphase != 0)
+       if (carphase != 7)
                return;
 
-       env = (up->lastenv[2] - up->lastenv[6]) / 2.;
        lope = (up->lastint[2] - up->lastint[6]) / 2.;
        if (lope > up->intmax)
                up->intmax = lope;
@@ -701,9 +705,6 @@ irig_base(
         * when three correct frames have been found.
         */
        up->pulse = (up->pulse + 1) % 10;
-       up->dcycles <<= 1;
-       if (env >=  (up->maxsignal + up->noise) / 2.)
-               up->dcycles |= 1;
        up->cycles <<= 1;
        if (lope >= (up->maxsignal + up->noise) / 2.)
                up->cycles |= 1;
@@ -712,8 +713,58 @@ irig_base(
                        up->errflg |= IRIG_ERR_SYNCH;
                up->pulse = 0;
        }
-       if (up->pulse != 0)
-               return;
+
+       /*
+        * Assemble the baud and max/min to get the slice level for the
+        * next baud. The slice level is based on the maximum over the
+        * first two bits and the minimum over the last two bits, with
+        * the slice level halfway between the maximum and minimum.
+        */
+       env = (up->lastenv[2] - up->lastenv[6]) / 2.;
+       up->dcycles <<= 1;
+       if (env >= up->slice)
+               up->dcycles |= 1;
+       switch(up->pulse) {
+
+       case 0:
+               irig_baud(peer, up->dcycles);
+               if (env < up->envmin)
+                       up->envmin = env;
+               up->slice = (up->envmax + up->envmin) / 2;
+               up->envmin = 1e6; up->envmax = -1e6;
+               break;
+
+       case 1:
+               up->envmax = env;
+               break;
+
+       case 2:
+               if (env > up->envmax)
+                       up->envmax = env;
+               break;
+
+       case 9:
+               up->envmin = env;
+               break;
+       }
+}
+
+/*
+ * irig_baud - update the PLL and decode the pulse-width signal
+ */
+static void
+irig_baud(
+       struct peer *peer,      /* peer structure pointer */
+       int     bits            /* decoded bits */
+       )
+{
+       struct refclockproc *pp;
+       struct irigunit *up;
+       double  dtemp;
+       l_fp    ltemp;
+
+        pp = peer->procptr;
+       up = (struct irigunit *)pp->unitptr;
 
        /*
         * The PLL time constant starts out small, in order to
@@ -725,7 +776,7 @@ irig_base(
        up->exing = -up->yxing;
        if (fabs(up->envxing - up->envphase) <= 1) {
                up->tcount++;
-               if (up->tcount > 50 * up->tc) {
+               if (up->tcount > 20 * up->tc) {
                        up->tc++;
                        if (up->tc > MAXTC)
                                up->tc = MAXTC;
@@ -740,44 +791,43 @@ irig_base(
        }
 
        /*
-        * Strike the character timestamp as the positive zero
-        * crossing of the first bit, accounting for the codec
-        * delay and filter delay.
+        * Strike the baud timestamp as the positive zero crossing of
+        * the first bit, accounting for the codec delay and filter
+        * delay.
         */
-       dtemp = up->decim * ((up->exing + 7 + BAUD) / SECOND) +
-           up->fdelay;
+       up->prvstamp = up->chrstamp;
+       dtemp = up->decim * (up->exing / SECOND) + up->fdelay;
        DTOLFP(dtemp, &ltemp);
        up->chrstamp = up->timestamp;
        L_SUB(&up->chrstamp, &ltemp);
 
        /*
-        * The data bits are collected in ten-bit frames. The first two
-        * bits are not used; the resulting patterns represent zero (0-2
-        * bits), one (3-5 bits) and position identifier PI (6-7 bits).
-        * The remaining patterns represent errors and are treated as
-        * zeros.
+        * The data bits are collected in ten-bit bauds. The first two
+        * bits are not used. The resulting patterns represent runs of
+        * 0-1 bits (0), 2-4 bits (1) and 5-7 bits (PI). The remaining
+        * 8-bit run represents a soft error and is treated as 0.
         */
        switch (up->dcycles & 0xff) {
 
-       case 0x00:              /* 0 */
+       case 0x00:              /* 0-1 bits (0) */
        case 0x80:
-       case 0xc0:
                irig_decode(peer, BIT0);
                break;
 
-       case 0xe0:              /* 1 */
+       case 0xc0:              /* 2-4 bits (1) */
+       case 0xe0:
        case 0xf0:
-       case 0xf8:
                irig_decode(peer, BIT1);
                break;
 
-       case 0xfc:              /* PI */
+       case 0xf8:              /* (5-7 bits (PI) */
+       case 0xfc:
        case 0xfe:
                irig_decode(peer, BITP);
                break;
 
-       default:                /* error */
-               irig_decode(peer, B0);
+       default:                /* 8 bits (error) */
+               irig_decode(peer, BIT0);
                up->errflg |= IRIG_ERR_DECODE;
        }
 }
@@ -786,7 +836,7 @@ irig_base(
 /*
  * irig_decode - decode the data
  *
- * This routine assembles bits into digits, digits into frames and
+ * This routine assembles bauds into digits, digits into frames and
  * frames into the timecode fields. Bits can have values of zero, one
  * or position identifier. There are four bits per digit, ten digits per
  * frame and ten frames per second.
@@ -803,10 +853,9 @@ irig_decode(
        /*
         * Local variables
         */
-       char    syncchar;       /* sync character (Spectracom) */
+       int     syncdig;        /* sync digit (Spectracom) */
        char    sbs[6];         /* binary seconds since 0h */
        char    spare[2];       /* mulligan digits */
-       int     i;
        int     temp;
 
         pp = peer->procptr;
@@ -815,9 +864,9 @@ irig_decode(
        /*
         * Assemble frame bits.
         */
-       up->bits <<= 1;
+       up->bits >>= 1;
        if (bit == BIT1) {
-               up->bits |= 1;
+               up->bits |= 0x200;
        } else if (bit == BITP && up->lastbit == BITP) {
 
                /*
@@ -827,31 +876,29 @@ irig_decode(
                 * so copy the character timestamp to the reference
                 * timestamp.
                 */
+               if (up->frmcnt != 1)
+                       up->errflg |= IRIG_ERR_SYNCH;
                up->frmcnt = 1;
-               up->refstamp = up->chrstamp;
+               up->refstamp = up->prvstamp;
        }
        up->lastbit = bit;
        if (up->frmcnt % SUBFLD == 0) {
 
                /*
                 * End of frame. Encode two hexadecimal digits in
-                * little-endian timecode field.
+                * little-endian timecode field. Note frame 1 is shifted
+                * right one bit to account for the marker PI.
                 */
                temp = up->bits;
-               i = (SUBFLD - 1 - up->frmcnt / SUBFLD) * 2;
-
-printf (" %d %1c%1c", i, hexchar[(temp >> 5) & 0xf], hexchar[temp & 0xf]);
-
-               up->timecode[i - 1] = hexchar[(temp >> 5) &
-                   0xf];
-
-
-               up->timecode[i - 2] = hexchar[temp & 0xf];
+               if (up->frmcnt == 10)
+                       temp >>= 1;
+               if (up->xptr >= 2) {
+                       up->timecode[--up->xptr] = hexchar[temp & 0xf];
+                       up->timecode[--up->xptr] = hexchar[(temp >> 5) &
+                           0xf];
+               }
                if (up->frmcnt == 0) {
 
-printf("\n");
-printf("%20s\n", up->timecode);
-
                        /*
                         * End of second. Decode the timecode and wind
                         * the clock. Not all IRIG generators have the
@@ -865,20 +912,41 @@ printf("%20s\n", up->timecode);
                         * refclock_process() will reject the timecode
                         * as invalid.
                         */
+                       up->xptr = 2 * SUBFLD;
                        if (sscanf((char *)up->timecode,
-                          "%6s%2d%c%2s%3d%2d%2d%2d", sbs, &pp->year,
-                           &syncchar, spare, &pp->day, &pp->hour,
+                          "%6s%2d%1d%2s%3d%2d%2d%2d", sbs, &pp->year,
+                           &syncdig, spare, &pp->day, &pp->hour,
                            &pp->minute, &pp->second) != 8)
                                pp->leap = LEAP_NOTINSYNC;
                        else
                                pp->leap = LEAP_NOWARNING;
                        up->second = (up->second + up->decim) % 60;
-                       if (pp->year > 0)
-                               pp->year += 2000;
+
+                       /*
+                        * Raise an alarm if the day field is zero,
+                        * which happens when signature control is
+                        * enabled and the device has lost
+                        * synchronization. Raise an alarm if the year
+                        * field is nonzero and the sync indicator is
+                        * zero, which happens when a Spectracom radio
+                        * has lost synchronization. Raise an alarm if
+                        * the expected second does not agree with the
+                        * decoded second, which happens with a garbled
+                        * IRIG signal. We are very particular.
+                        */
+                       if (pp->day == 0 || pp->year != 0 && syncdig ==
+                           0)
+                               up->errflg |= IRIG_ERR_SIGERR;
                        if (pp->second != up->second)
                                up->errflg |= IRIG_ERR_CHECK;
                        up->second = pp->second;
-                       if (up->errflg == 0) {
+
+                       /*
+                        * Wind the clock only if there are no errors
+                        * and the time constant has reached the
+                        * maximum.
+                        */
+                       if (up->errflg == 0 && up->tc == MAXTC) {
                                pp->lastref = pp->lastrec;
                                pp->lastrec = up->refstamp;
                                if (!refclock_process(pp))
@@ -886,8 +954,8 @@ printf("%20s\n", up->timecode);
                                            CEVNT_BADTIME);
                        }
                        sprintf(pp->a_lastcode,
-                           "%02x %c %02d %03d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.2f %6.1f %s",
-                           up->errflg, syncchar, pp->year, pp->day,
+                           "%02x %02d %03d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.2f %6.1f %s",
+                           up->errflg, pp->year, pp->day,
                            pp->hour, pp->minute, pp->second,
                            up->maxsignal, up->gain, up->modndx,
                            up->tc, up->exing * 1e6 / SECOND, up->freq *
@@ -949,11 +1017,10 @@ irig_poll(
 /*
  * irig_gain - adjust codec gain
  *
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
+ * This routine is called at the end of each second. It uses the AGC to
+ * bradket the maximum signal level between MINAMP and MAXAMP to avoid
+ * hunting. The routine also jiggles the input port and selectively
+ * mutes the monitor.
  */
 static void
 irig_gain(
@@ -971,19 +1038,19 @@ irig_gain(
         * gain control field. Thus, it may take awhile for changes to
         * wiggle the hardware bits.
         */
-       if (up->clipcnt == 0) {
+       if (up->maxsignal < MINAMP) {
                up->gain += 4;
                if (up->gain > MAXGAIN)
                        up->gain = MAXGAIN;
-       } else if (up->clipcnt > MAXCLP) {
+       } else if (up->maxsignal > MAXAMP) {
                up->gain -= 4;
                if (up->gain < 0)
                        up->gain = 0;
        }
        audio_gain(up->gain, up->mongain, up->port);
-       up->clipcnt = 0;
 }
 
+
 #else
 int refclock_irig_bs;
 #endif /* REFCLOCK */
index 9ecd25f37ea8148b3033812a60f0580f1c4a8e38..430f09fb5d653233e8ca44e778b9164e4b852699 100644 (file)
  * tuned automatically using this program as propagation conditions
  * change throughout the weasons, both day and night.
  *
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a workstation running Solaris, SunOS
- * FreeBSD or Linux, and with a little help, other workstations with
- * similar codecs or sound cards. In this implementation, only one audio
- * driver and codec can be supported on a single machine.
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
  *
  * The demodulation and decoding algorithms used in this driver are
  * based on those developed for the TAPR DSP93 development board and the
 #define SECWAR         0x40    /* 3 leap second warning */
 
 /*
- * The on-time synchronization point for the driver is the second epoch
- * sync pulse produced by the FIR matched filters. As the 5-ms delay of
- * these filters is compensated, the program delay is 1.1 ms due to the
- * 600-Hz IIR bandpass filter. The measured receiver delay is 4.7 ms and
- * the codec delay about 0.5 ms. The additional propagation delay
- * specific to each receiver location can be programmed in the fudge
- * time1 and time2 values for WWV and WWVH, respectively.
+ * The on-time synchronization point is the positive-going zero crossing
+ * of the first cycle of the 5-ms second pulse. The IIR baseband filter
+ * phase delay is 0.91 ms, while the receiver delay is approximately 4.7
+ * ms at 1000 Hz. The fudge value -0.45 ms due to the codec and other
+ * causes was determined by calibrating to a PPS signal from a GPS
+ * receiver. The additional propagation delay specific to each receiver
+ * location can be  programmed in the fudge time1 and time2 values for
+ * WWV and WWVH, respectively.
+ *
+ * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
+ * generally within .02 ms short-term with .02 ms jitter. The long-term
+ * offsets vary up to 0.3 ms due to ionosperhic layer height variations.
+ * The processor load due to the driver is 5.8 percent.
  */
-#define PDELAY (.0011 + .0047 + .0005) /* net system delay (s) */
+#define PDELAY ((.91 + 4.7 - 0.45) / 1000) /* system delay (s) */
 
 /*
  * Table of sine values at 4.5-degree increments. This is used by the
@@ -369,7 +376,7 @@ struct progx progx[] = {
 };
 
 /*
- * BCD coefficients for maximum likelihood digit decode
+ * BCD coefficients for maximum-likelihood digit decode
  */
 #define P15    1.              /* max positive number */
 #define N15    -1.             /* max negative number */
@@ -451,14 +458,14 @@ char dstcod[] = {
 /*
  * The decoding matrix consists of nine row vectors, one for each digit
  * of the timecode. The digits are stored from least to most significant
- * order. The maximum likelihood timecode is formed from the digits
- * corresponding to the maximum likelihood values reading in the
+ * order. The maximum-likelihood timecode is formed from the digits
+ * corresponding to the maximum-likelihood values reading in the
  * opposite order: yy ddd hh:mm.
  */
 struct decvec {
        int radix;              /* radix (3, 4, 6, 10) */
        int digit;              /* current clock digit */
-       int mldigit;            /* maximum likelihood digit */
+       int mldigit;            /* maximum-likelihood digit */
        int count;              /* match count */
        double digprb;          /* max digit probability */
        double digsnr;          /* likelihood function (dB) */
@@ -507,6 +514,7 @@ struct wwvunit {
        l_fp    tick;           /* audio sample increment */
        double  phase, freq;    /* logical clock phase and frequency */
        double  monitor;        /* audio monitor point */
+       double  pdelay;         /* propagation delay (s) */
 #ifdef ICOM
        int     fd_icom;        /* ICOM file descriptor */
 #endif /* ICOM */
@@ -517,7 +525,7 @@ struct wwvunit {
         * Audio codec variables
         */
        double  comp[SIZE];     /* decompanding table */
-       int     port;           /* codec port */
+       int     port;           /* codec port */
        int     gain;           /* codec gain */
        int     mongain;        /* codec monitor gain */
        int     clipcnt;        /* sample clipped count */
@@ -966,7 +974,6 @@ wwv_rf(
        static int epopos;      /* epoch second sync position buffer */
 
        static int iniflg;      /* initialization flag */
-       int     pdelay;         /* propagation delay (samples) */
        int     epoch;          /* comb filter index */
        double  dtemp;
        int     i;
@@ -1004,7 +1011,7 @@ wwv_rf(
         * compensate for the radio audio response at 100 Hz.
         *
         * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
-        * passband ripple, -50 dB stopband ripple.
+        * passband ripple, -50 dB stopband ripple, phase delay 0.97 ms.
         */
        data = (lpf[4] = lpf[3]) * 8.360961e-01;
        data += (lpf[3] = lpf[2]) * -3.481740e+00;
@@ -1048,7 +1055,7 @@ wwv_rf(
         * tones and most of the noise and voice modulation components.
         *
         * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
-        * passband ripple, -50 dB stopband ripple.
+        * passband ripple, -50 dB stopband ripple, phase delay 0.91 ms.
         */
        syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
        syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
@@ -1221,18 +1228,14 @@ wwv_rf(
         * provides a resolution of one sample (125 us). The filters run
         * only if the station has been reliably determined.
         */
-       if (up->status & SELV) {
-               pdelay = (int)(pp->fudgetime1 * SECOND);
+       if (up->status & SELV)
                mfsync = sqrt(csiamp * csiamp + csqamp * csqamp) /
                    TCKCYC;
-       } else if (up->status & SELH) {
-               pdelay = (int)(pp->fudgetime2 * SECOND);
+       else if (up->status & SELH)
                mfsync = sqrt(hsiamp * hsiamp + hsqamp * hsqamp) /
                    TCKCYC;
-       } else {
-               pdelay = 0;
+       else
                mfsync = 0;
-       }
 
        /*
         * Enhance the seconds sync pulse using a 1-s (8000-sample) comb
@@ -1252,6 +1255,7 @@ wwv_rf(
 
                epomax = dtemp;
                epopos = epoch;
+               up->timestamp = up->timestamp;
                j = epoch - 6 * MS;
                if (j < 0)
                        j += SECOND;
@@ -1260,7 +1264,7 @@ wwv_rf(
        if (epoch == 0) {
                up->epomax = epomax;
                up->eposnr = wwv_snr(epomax, nxtmax);
-               epopos -= pdelay + TCKCYC * MS;
+               epopos -= TCKCYC * MS;
                if (epopos < 0)
                        epopos += SECOND;
                wwv_endpoc(peer, epopos);
@@ -2089,7 +2093,7 @@ wwv_clock(
                        pp->disp = 0;
                        pp->lastref = up->timestamp;
                        refclock_process_offset(pp, offset,
-                           up->timestamp, PDELAY);
+                           up->timestamp, PDELAY + up->pdelay);
                        refclock_receive(peer);
                }
        }
@@ -2104,12 +2108,12 @@ wwv_clock(
 
 
 /*
- * wwv_corr4 - determine maximum likelihood digit
+ * wwv_corr4 - determine maximum-likelihood digit
  *
  * This routine correlates the received digit vector with the BCD
  * coefficient vectors corresponding to all valid digits at the given
  * position in the decoding matrix. The maximum value corresponds to the
- * maximum likelihood digit, while the ratio of this value to the next
+ * maximum-likelihood digit, while the ratio of this value to the next
  * lower value determines the likelihood function. Note that, if the
  * digit is invalid, the likelihood vector is averaged toward a miss.
  */
@@ -2158,9 +2162,9 @@ wwv_corr4(
        vp->digsnr = wwv_snr(topmax, nxtmax);
 
        /*
-        * The current maximum likelihood digit is compared to the last
-        * maximum likelihood digit. If different, the compare counter
-        * and maximum likelihood digit are reset.  When the compare
+        * The current maximum-likelihood digit is compared to the last
+        * maximum-likelihood digit. If different, the compare counter
+        * and maximum-likelihood digit are reset.  When the compare
         * counter reaches the BCMP threshold (3), the digit is assumed
         * correct. When the compare counter of all nine digits have
         * reached threshold, the clock is assumed correct.
@@ -2170,7 +2174,7 @@ wwv_corr4(
         * not considered correct until all nine clock digits have
         * reached threshold. This is intended as eye candy, but avoids
         * mistakes when the signal is low and the SNR is very marginal.
-        * once correctly set, the maximum likelihood digit is ignored
+        * once correctly set, the maximum-likelihood digit is ignored
         * on the assumption the clock will always be correct unless for
         * some reason it drifts to a different second.
         */
@@ -2308,7 +2312,7 @@ wwv_tsec(
  * This routine rotates a likelihood vector one position and increments
  * the clock digit modulo the radix. It returns the new clock digit or
  * zero if a carry occurred. Once synchronized, the clock digit will
- * match the maximum likelihood digit corresponding to that position.
+ * match the maximum-likelihood digit corresponding to that position.
  */
 static int
 carry(
@@ -2453,8 +2457,14 @@ wwv_newchan(
                up->sptr = sp;
                memcpy(&pp->refid, sp->refid, 4);
                peer->refid = pp->refid;
-               up->status |= METRIC;
+               if (sp->select & SELV)
+                       up->pdelay = pp->fudgetime1;
+               else if (sp->select & SELH)
+                       up->pdelay = pp->fudgetime2;
+               else
+                       up->pdelay = 0;
                rval = TRUE;
+               up->status |= METRIC;
        }
 #ifdef ICOM
        if (up->fd_icom > 0)
@@ -2657,7 +2667,8 @@ timecode(
  * there are no clips, the gain is bumped up; if there are more than
  * MAXCLP clips (100), it is bumped down. The decoder is relatively
  * insensitive to amplitude, so this crudity works just peachy. The
- * input port is set and the error flag is cleared, mostly to be ornery.
+ * routine also jiggles the input port and selectively mutes the
+ * monitor.
  */
 static void
 wwv_gain(
index ebad7f85463b940cdd3f6401ffb0297ea7ed7eea..6eef142e4ad26e87080a4133206d7b1a40acd438 100644 (file)
@@ -372,8 +372,6 @@ wwvb_receive(
         */
        if (!refclock_process(pp))
                refclock_report(peer, CEVNT_BADTIME);
-       if (peer->disp > MAXDISTANCE)
-               refclock_receive(peer);
 }