Left uncorrected, the local clock runs at the offset and frequency resulting from its last update. An update is produced by an event that results in a valid clock selection. It consists of a signed 48bit integer in whole milliseconds and fraction, with fraction point to the
left of bit 32. If the magnitude is greater than the maximum aperture CLOCK.MAX, a step adjustment is required, in which case proceed as described later. Otherwise, a gradual phase adjustment is performed. Normally, the update is computed by the NTP algorithms described previously; however, if the
PPS counter is greater than zero, the value of the PPSAdjust register is used instead. Let u be a 32bit quantity with bits 031 set as bits 1647 of the update. If some of the loworder bits of the update are unimplemented, they are set as the value of the sign bit. These operations move the
fraction point of u to the left of bit 16 and minimize the effects of truncation and roundoff errors. Let b be the number of leading zeros of the absolute value of the Compliance register and let c be the number of leading zeros of the Watchdog counter, both of which are easily computed by compact
loops. Then, set b to
b = b  16 + CLOCK.COMP
and clamp it to be not less than zero. This represents the logarithm of the loop time constant. Then, set c to
c = 10  c
and clamp it to be not greater than NTP.MAXPOLL  NTP.MINPOLL. This represents the logarithm of the integration interval since the last update. The clamps insure stable operation under typical conditions encountered in the Internet. Then, compute new values for the ClockAdjust
and SkewCompensation registers
x = u >> b ,
y = y + (u >> (b + b  c)).
Finally, compute the exponential average
z = z + (u << (b + CLOCK.MULT)  z) >> CLOCK.WEIGHT,
where the left shift realigns the fraction point for greater precision and ease of computation.
At each adjustment interval the final clock correction consisting of two components is determined. The first (phase) component consists of the quantity
x >> CLOCK.PHASE> ,
which is then subtracted from the previous contents of the ClockAdjust register to form the new contents of that register. The second (frequency) component consists of the quantity
y >> CLOCK.FREQ.
The sum of the phase and frequency components is the final clock correction, which is then added to the Clock register. Finally, the Watchdog counter is set to zero. Operation continues in this way until a
new correction is introduced.
The value of b computed above can be used to update the poll interval system variable (sys.poll). This functions as an adaptive parameter that provides a very valuable feature which reduces the polling overhead, especially if the clockcombining algorithm described in Appendix F
is used:
sys.poll < b + NTP.MINPOLL.
Under conditions when update noise is high or the hardware oscillator frequency is changing relatively rapidly due to environmental conditions, the magnitude of the compliance increases. With the parameters specified, this causes the loop bandwidth (reciprocal of time constant)
to increase and the poll interval to decrease, eventually to NTP.MINPOLL seconds. When noise is low and the hardware oscillator very stable, the compliance decreases, which causes the loop bandwidth to decrease and the poll interval to increase, eventually to NTP.MAXPOLL seconds.
The parameters in Table 6 have been selected so that, under good conditions with updates in the order of a few milliseconds, a precision of a millisecond per day (about .01 ppm or 108), can be achieved. Care is required in the implementation to insure monotonicity of the Clock
register and to preserve the highest precision while minimizing the propagation of roundoff errors. Since all of the multiply/divide operations (except those involved with the 1pps pulses) computed in real time can be approximated by bitwiseshift operations, it is not necessary to implement a
full multiply/divide capability in hardware or
software.
In the various implementations of NTP for many Unixbased systems it has been the common experience that the single most important factor affecting localclock stability is the matching of the phase and frequency coefficients to the particular kernel implementation. It is vital
that these coefficients be engineered according to the model values, for otherwise the PLL can fail to track normal oscillator
variations and can even become unstable.
