LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
fabs(estimated_offset),
(estimated_offset >= 0) ? "fast" : "slow");
- LCL_AccumulateOffset(estimated_offset);
+ LCL_AccumulateOffset(estimated_offset, 0.0);
}
} else {
usec = (long)(ntohl(rx_message->data.doffset.usec));
doffset = (double) sec + 1.0e-6 * (double) usec;
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
- LCL_AccumulateOffset(doffset);
+ LCL_AccumulateOffset(doffset, 0.0);
tx_message->status = htons(STT_SUCCESS);
}
/* ================================================== */
void
-LCL_AccumulateOffset(double offset)
+LCL_AccumulateOffset(double offset, double corr_rate)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL);
- (*drv_accrue_offset)(offset);
+ (*drv_accrue_offset)(offset, corr_rate);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
/* ================================================== */
void
-LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
+LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm);
- (*drv_accrue_offset)(doffset);
+ (*drv_accrue_offset)(doffset, corr_rate);
/* Dispatch to all handlers */
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
return 0;
/* Cancel remaining slew and make the step */
- LCL_AccumulateOffset(correction);
+ LCL_AccumulateOffset(correction, 0.0);
LCL_ApplyStepOffset(-correction);
LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.3f seconds", correction);
/* Routine to apply an offset (in seconds) to the local clock. The
argument should be positive to move the clock backwards (i.e. the
local clock is currently fast of true time), or negative to move it
- forwards (i.e. it is currently slow of true time). */
+ forwards (i.e. it is currently slow of true time). Provided is also
+ a suggested correction rate (correction time * offset). */
-extern void LCL_AccumulateOffset(double offset);
+extern void LCL_AccumulateOffset(double offset, double corr_rate);
/* Routine to apply an immediate offset by doing a sudden step if
possible. (Intended for use after an initial estimate of offset has
/* Perform the combination of modifying the frequency and applying
a slew, in one easy step */
-extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
+extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
/* Routine to read the system precision as a log to base 2 value. */
extern int LCL_GetSysPrecisionAsLog(void);
typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
/* System driver to accrue an offset. A positive argument means slew
- the clock forwards. */
-typedef void (*lcl_AccrueOffsetDriver)(double offset);
+ the clock forwards. The suggested correction rate of time to correct the
+ offset is given in 'corr_rate'. */
+typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
/* System driver to apply a step offset. A positive argument means step
the clock forwards. */
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
+ double offset_sd,
double frequency,
double skew,
double root_delay,
double abs_freq_ppm;
double update_interval;
double elapsed;
+ double correction_rate;
struct timeval now;
assert(initialised);
}
last_ref_update = now;
+ /* We want to correct the offset quickly, but we also want to keep the
+ frequency error caused by the correction itself low.
+
+ Define correction rate as the area of the region bounded by the graph of
+ offset corrected in time. Set the rate so that the time needed to correct
+ an offset equal to the current sourcestats stddev will be equal to the
+ update interval (assuming linear adjustment). The offset and the
+ time needed to make the correction are inversely proportional.
+
+ This is only a suggestion and it's up to the system driver how the
+ adjustment will be executed. */
+
+ correction_rate = 0.5 * offset_sd * update_interval;
+
/* Eliminate updates that are based on totally unreliable frequency
information */
our_residual_freq = new_freq - our_frequency;
maybe_log_offset(our_offset);
- LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset);
+ LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset, correction_rate);
} else {
LOG(LOGS_INFO, LOGF_Reference, "Skew %f too large to track, offset=%f", skew, our_offset);
#endif
maybe_log_offset(our_offset);
- LCL_AccumulateOffset(our_offset);
+ LCL_AccumulateOffset(our_offset, correction_rate);
our_residual_freq = frequency;
}
our_residual_freq = 0.0;
maybe_log_offset(offset);
- LCL_AccumulateFrequencyAndOffset(frequency, offset);
+ LCL_AccumulateFrequencyAndOffset(frequency, offset, 0.0);
maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
IPAddr *ref_ip,
struct timeval *ref_time,
double offset,
+ double offset_sd,
double frequency,
double skew,
double root_delay,
sys_error_now = rtc_error_now - coef_seconds_fast;
LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now);
- LCL_AccumulateOffset(sys_error_now);
+ LCL_AccumulateOffset(sys_error_now, 0.0);
} else {
LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time");
}
sources[selected_source_index]->ip_addr,
&ref_time,
src_offset,
+ src_offset_sd,
src_frequency,
src_skew,
src_root_delay,
time) */
static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
{
/* Add the new offset to the register */
offset_register += offset;
slew backwards */
static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;
slew backwards */
static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;
slew backwards */
static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
{
stop_adjust();
offset_register += offset;