summaryrefslogtreecommitdiff
path: root/refclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'refclock.c')
-rw-r--r--refclock.c103
1 files changed, 58 insertions, 45 deletions
diff --git a/refclock.c b/refclock.c
index 862a624..4686af0 100644
--- a/refclock.c
+++ b/refclock.c
@@ -48,7 +48,7 @@ extern RefclockDriver RCL_PHC_driver;
struct FilterSample {
double offset;
double dispersion;
- struct timeval sample_time;
+ struct timespec sample_time;
};
struct MedianFilter {
@@ -77,6 +77,7 @@ struct RCL_Instance_Record {
int leap_status;
int pps_rate;
int pps_active;
+ int max_lock_age;
struct MedianFilter filter;
uint32_t ref_id;
uint32_t lock_ref;
@@ -92,24 +93,24 @@ static ARR_Instance refclocks;
static LOG_FileID logfileid;
-static int valid_sample_time(RCL_Instance instance, struct timeval *raw, struct timeval *cooked);
-static int pps_stratum(RCL_Instance instance, struct timeval *tv);
+static int valid_sample_time(RCL_Instance instance, struct timespec *raw, struct timespec *cooked);
+static int pps_stratum(RCL_Instance instance, struct timespec *ts);
static void poll_timeout(void *arg);
-static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
+static void slew_samples(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything);
static void add_dispersion(double dispersion, void *anything);
-static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
+static void log_sample(RCL_Instance instance, struct timespec *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
static void filter_init(struct MedianFilter *filter, int length, double max_dispersion);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
-static void filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion);
-static int filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
+static void filter_add_sample(struct MedianFilter *filter, struct timespec *sample_time, double offset, double dispersion);
+static int filter_get_last_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion);
static int filter_get_samples(struct MedianFilter *filter);
static int filter_select_samples(struct MedianFilter *filter);
-static int filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion);
-static void filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset);
+static int filter_get_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion);
+static void filter_slew_samples(struct MedianFilter *filter, struct timespec *when, double dfreq, double doffset);
static void filter_add_dispersion(struct MedianFilter *filter, double dispersion);
static RCL_Instance
@@ -202,6 +203,7 @@ RCL_AddRefclock(RefclockParameters *params)
inst->leap_status = LEAP_Normal;
inst->pps_rate = params->pps_rate;
inst->pps_active = 0;
+ inst->max_lock_age = params->max_lock_age;
inst->lock_ref = params->lock_ref_id;
inst->offset = params->offset;
inst->delay = params->delay;
@@ -300,7 +302,7 @@ RCL_StartRefclocks(void)
}
void
-RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
+RCL_ReportSource(RPT_SourceReport *report, struct timespec *now)
{
unsigned int i;
uint32_t ref_id;
@@ -362,13 +364,13 @@ RCL_GetDriverOption(RCL_Instance instance, char *name)
}
int
-RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, int leap)
+RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap)
{
double correction, dispersion;
- struct timeval cooked_time;
+ struct timespec cooked_time;
LCL_GetOffsetCorrection(sample_time, &correction, &dispersion);
- UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
+ UTI_AddDoubleToTimespec(sample_time, correction, &cooked_time);
dispersion += instance->precision;
/* Make sure the timestamp and offset provided by the driver are sane */
@@ -400,16 +402,16 @@ RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset,
}
int
-RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
+RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
{
double correction, dispersion, offset;
- struct timeval cooked_time;
+ struct timespec cooked_time;
int rate;
NTP_Leap leap;
leap = LEAP_Normal;
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
- UTI_AddDoubleToTimeval(pulse_time, correction, &cooked_time);
+ UTI_AddDoubleToTimespec(pulse_time, correction, &cooked_time);
dispersion += instance->precision;
if (!UTI_IsTimeOffsetSane(pulse_time, 0.0) ||
@@ -430,7 +432,7 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
if (instance->lock_ref != -1) {
RCL_Instance lock_refclock;
- struct timeval ref_sample_time;
+ struct timespec ref_sample_time;
double sample_diff, ref_offset, ref_dispersion, shift;
lock_refclock = get_refclock(instance->lock_ref);
@@ -443,8 +445,8 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
ref_dispersion += filter_get_avg_sample_dispersion(&lock_refclock->filter);
- UTI_DiffTimevalsToDouble(&sample_diff, &cooked_time, &ref_sample_time);
- if (fabs(sample_diff) >= 2.0 / rate) {
+ sample_diff = UTI_DiffTimespecsToDouble(&cooked_time, &ref_sample_time);
+ if (fabs(sample_diff) >= (double)instance->max_lock_age / rate) {
DEBUG_LOG(LOGF_Refclock, "refclock pulse ignored samplediff=%.9f",
sample_diff);
return 0;
@@ -469,7 +471,7 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
DEBUG_LOG(LOGF_Refclock, "refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
second, offset, ref_offset - offset, sample_diff);
} else {
- struct timeval ref_time;
+ struct timespec ref_time;
int is_synchronised, stratum;
double root_delay, root_dispersion, distance;
uint32_t ref_id;
@@ -504,22 +506,22 @@ RCL_AddPulse(RCL_Instance instance, struct timeval *pulse_time, double second)
}
static int
-valid_sample_time(RCL_Instance instance, struct timeval *raw, struct timeval *cooked)
+valid_sample_time(RCL_Instance instance, struct timespec *raw, struct timespec *cooked)
{
- struct timeval raw_time, last_sample_time;
+ struct timespec now_raw, last_sample_time;
double diff, last_offset, last_dispersion;
- LCL_ReadRawTime(&raw_time);
- UTI_DiffTimevalsToDouble(&diff, &raw_time, raw);
+ LCL_ReadRawTime(&now_raw);
+ diff = UTI_DiffTimespecsToDouble(&now_raw, raw);
if (diff < 0.0 || diff > UTI_Log2ToDouble(instance->poll + 1) ||
(filter_get_samples(&instance->filter) > 0 &&
filter_get_last_sample(&instance->filter, &last_sample_time,
&last_offset, &last_dispersion) &&
- UTI_CompareTimevals(&last_sample_time, cooked) >= 0)) {
+ UTI_CompareTimespecs(&last_sample_time, cooked) >= 0)) {
DEBUG_LOG(LOGF_Refclock, "%s refclock sample not valid age=%.6f raw=%s cooked=%s",
UTI_RefidToString(instance->ref_id), diff,
- UTI_TimevalToString(raw), UTI_TimevalToString(cooked));
+ UTI_TimespecToString(raw), UTI_TimespecToString(cooked));
return 0;
}
@@ -527,9 +529,9 @@ valid_sample_time(RCL_Instance instance, struct timeval *raw, struct timeval *co
}
static int
-pps_stratum(RCL_Instance instance, struct timeval *tv)
+pps_stratum(RCL_Instance instance, struct timespec *ts)
{
- struct timeval ref_time;
+ struct timespec ref_time;
int is_synchronised, stratum;
unsigned int i;
double root_delay, root_dispersion;
@@ -537,7 +539,7 @@ pps_stratum(RCL_Instance instance, struct timeval *tv)
uint32_t ref_id;
RCL_Instance refclock;
- REF_GetReferenceParams(tv, &is_synchronised, &leap, &stratum,
+ REF_GetReferenceParams(ts, &is_synchronised, &leap, &stratum,
&ref_id, &ref_time, &root_delay, &root_dispersion);
/* Don't change our stratum if the local reference is active
@@ -574,7 +576,7 @@ poll_timeout(void *arg)
if (!(inst->driver->poll && inst->driver_polled < (1 << (inst->poll - inst->driver_poll)))) {
double offset, dispersion;
- struct timeval sample_time;
+ struct timespec sample_time;
int sample_ok, stratum;
sample_ok = filter_get_sample(&inst->filter, &sample_time, &offset, &dispersion);
@@ -602,7 +604,7 @@ poll_timeout(void *arg)
}
static void
-slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
+slew_samples(struct timespec *raw, struct timespec *cooked, double dfreq,
double doffset, LCL_ChangeType change_type, void *anything)
{
unsigned int i;
@@ -625,7 +627,7 @@ add_dispersion(double dispersion, void *anything)
}
static void
-log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
+log_sample(RCL_Instance instance, struct timespec *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion)
{
char sync_stats[4] = {'N', '+', '-', '?'};
@@ -635,7 +637,7 @@ log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int
if (!filtered) {
LOG_FileWrite(logfileid, "%s.%06d %-5s %3d %1c %1d %13.6e %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
- (int)sample_time->tv_usec,
+ (int)sample_time->tv_nsec / 1000,
UTI_RefidToString(instance->ref_id),
instance->driver_polled,
sync_stats[instance->leap_status],
@@ -646,7 +648,7 @@ log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int
} else {
LOG_FileWrite(logfileid, "%s.%06d %-5s - %1c - - %13.6e %10.3e",
UTI_TimeToLogForm(sample_time->tv_sec),
- (int)sample_time->tv_usec,
+ (int)sample_time->tv_nsec / 1000,
UTI_RefidToString(instance->ref_id),
sync_stats[instance->leap_status],
cooked_offset,
@@ -699,7 +701,7 @@ filter_get_avg_sample_dispersion(struct MedianFilter *filter)
}
static void
-filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, double offset, double dispersion)
+filter_add_sample(struct MedianFilter *filter, struct timespec *sample_time, double offset, double dispersion)
{
filter->index++;
filter->index %= filter->length;
@@ -712,11 +714,11 @@ filter_add_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
filter->samples[filter->index].dispersion = dispersion;
DEBUG_LOG(LOGF_Refclock, "filter sample %d t=%s offset=%.9f dispersion=%.9f",
- filter->index, UTI_TimevalToString(sample_time), offset, dispersion);
+ filter->index, UTI_TimespecToString(sample_time), offset, dispersion);
}
static int
-filter_get_last_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
+filter_get_last_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion)
{
if (filter->last < 0)
return 0;
@@ -835,7 +837,7 @@ filter_select_samples(struct MedianFilter *filter)
}
static int
-filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, double *offset, double *dispersion)
+filter_get_sample(struct MedianFilter *filter, struct timespec *sample_time, double *offset, double *dispersion)
{
struct FilterSample *s, *ls;
int i, n, dof;
@@ -852,7 +854,7 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
for (i = 0; i < n; i++) {
s = &filter->samples[filter->selected[i]];
- UTI_DiffTimevalsToDouble(&filter->x_data[i], &s->sample_time, &ls->sample_time);
+ filter->x_data[i] = UTI_DiffTimespecsToDouble(&s->sample_time, &ls->sample_time);
filter->y_data[i] = s->offset;
filter->w_data[i] = s->dispersion;
}
@@ -927,7 +929,7 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
if (d < e)
d = e;
- UTI_AddDoubleToTimeval(&ls->sample_time, x, sample_time);
+ UTI_AddDoubleToTimespec(&ls->sample_time, x, sample_time);
*offset = y;
*dispersion = d;
@@ -937,15 +939,26 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
}
static void
-filter_slew_samples(struct MedianFilter *filter, struct timeval *when, double dfreq, double doffset)
+filter_slew_samples(struct MedianFilter *filter, struct timespec *when, double dfreq, double doffset)
{
- int i;
+ int i, first, last;
double delta_time;
- struct timeval *sample;
+ struct timespec *sample;
- for (i = 0; i < filter->used; i++) {
+ if (filter->last < 0)
+ return;
+
+ /* always slew the last sample as it may be needed by PPS refclocks */
+ if (filter->used > 0) {
+ first = 0;
+ last = filter->used - 1;
+ } else {
+ first = last = filter->last;
+ }
+
+ for (i = first; i <= last; i++) {
sample = &filter->samples[i].sample_time;
- UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
+ UTI_AdjustTimespec(sample, when, sample, &delta_time, dfreq, doffset);
filter->samples[i].offset -= delta_time;
}
}