/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(afreq_ppm);
+ afreq_ppm = (*drv_set_freq)(afreq_ppm);
dfreq = (afreq_ppm - current_freq_ppm) / (1.0e6 + current_freq_ppm);
{
ChangeListEntry *ptr;
struct timeval raw, cooked;
+ double old_freq_ppm;
+
+ old_freq_ppm = current_freq_ppm;
/* Work out new absolute frequency. Note that absolute frequencies
are handled in units of ppm, whereas the 'dfreq' argument is in
current_freq_ppm = (1.0 + dfreq) * current_freq_ppm + 1.0e6 * dfreq;
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(current_freq_ppm);
+ current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
+ dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm);
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL);
#endif
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(current_freq_ppm);
+ 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);
/* Dispatch to all handlers */
/* ================================================== */
-void
+double
LCL_SetTempComp(double comp)
{
+ double uncomp_freq_ppm;
+
if (temp_comp_ppm == comp)
- return;
+ return comp;
/* Undo previous compensation */
current_freq_ppm = (current_freq_ppm + temp_comp_ppm) /
(1.0 - 1.0e-6 * temp_comp_ppm);
+ uncomp_freq_ppm = current_freq_ppm;
+
/* Apply new compensation */
current_freq_ppm = current_freq_ppm * (1.0 - 1.0e-6 * comp) - comp;
- temp_comp_ppm = comp;
-
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(current_freq_ppm);
+ current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
- return;
+ temp_comp_ppm = (uncomp_freq_ppm - current_freq_ppm) /
+ (1.0e-6 * uncomp_freq_ppm + 1.0);
+
+ return temp_comp_ppm;
}
/* ================================================== */
/* Routine to set a frequency correction (in ppm) that should be applied
to local clock to compensate for temperature changes. A positive
- argument means that the clock frequency should be increased. */
-extern void LCL_SetTempComp(double comp);
+ argument means that the clock frequency should be increased. Return the
+ actual compensation (may be different from the requested compensation
+ due to clamping or rounding). */
+extern double LCL_SetTempComp(double comp);
#endif /* GOT_LOCAL_H */
/* System driver to set the current local frequency, in ppm relative
to nominal. A positive value indicates that the local clock runs
- fast when uncompensated. */
-typedef void (*lcl_SetFrequencyDriver)(double freq_ppm);
+ fast when uncompensated. Return actual frequency (may be different
+ from the requested frequency due to clamping or rounding). */
+typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
/* System driver to accrue an offset. A positive argument means slew
the clock forwards. */
convention is that this is called with a positive argument if the local
clock runs fast when uncompensated. */
-static void
+static double
set_frequency(double freq_ppm)
{
long required_tick;
required_tick = slewing_tick;
}
- if (TMX_SetFrequency(scaled_freq, required_tick) < 0) {
+ if (TMX_SetFrequency(&scaled_freq, required_tick) < 0) {
LOG_FATAL(LOGF_SysLinux, "adjtimex failed for set_frequency, freq_ppm=%10.4e scaled_freq=%10.4e required_tick=%ld",
freq_ppm, scaled_freq, required_tick);
}
current_total_tick;
adjust_fast_slew(old_total_tick, old_delta_tick);
}
+
+ return dhz * (nominal_tick - current_tick) - scaled_freq / freq_scale;
}
/* ================================================== */
/* ================================================== */
-static void
+static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
+
+ return current_freq * 1.0e6;
}
/* ================================================== */
/* ================================================== */
-static void
+static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
+
+ return current_freq * 1.0e6;
}
/* ================================================== */
/* ================================================== */
-static void
+static double
set_frequency(double new_freq_ppm)
{
stop_adjust();
current_freq = new_freq_ppm * 1.0e-6;
start_adjust();
+
+ return current_freq * 1.0e6;
}
/* ================================================== */
/* Don't allow corrections above 10 ppm */
if (fabs(comp) < 10.0) {
- LCL_SetTempComp(comp);
+ comp = LCL_SetTempComp(comp);
if (logfileid != -1) {
struct timeval now;
}
int
-TMX_SetFrequency(double freq, long tick)
+TMX_SetFrequency(double *freq, long tick)
{
struct timex txc;
txc.modes = ADJ_TICK | ADJ_FREQUENCY | ADJ_STATUS;
- txc.freq = (long)(freq * (double)(1 << SHIFT_USEC));
+ txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
+ *freq = txc.freq / (double)(1 << SHIFT_USEC);
txc.tick = tick;
txc.status = STA_UNSYNC; /* Prevent any of the FLL/PLL stuff coming
up */
int TMX_SetTick(long tick);
int TMX_ApplyOffset(long *offset);
-int TMX_SetFrequency(double freq, long tick);
+int TMX_SetFrequency(double *freq, long tick);
int TMX_GetFrequency(double *freq);
int TMX_GetOffsetLeftOld(long *offset);
int TMX_GetOffsetLeft(long *offset);