diff --git a/conf.c b/conf.c index aafdba3..6fa5eee 100644 --- a/conf.c +++ b/conf.c @@ -676,7 +676,7 @@ parse_refclock(char *line) int n, poll, dpoll, filter_length, pps_rate, min_samples, max_samples, sel_options; int max_lock_age, pps_forced; uint32_t ref_id, lock_ref_id; - double offset, delay, precision, max_dispersion; + double offset, delay, precision, max_dispersion, pulse_width; char *p, *cmd, *name, *param; unsigned char ref[5]; RefclockParameters *refclock; @@ -693,6 +693,7 @@ parse_refclock(char *line) delay = 1e-9; precision = 0.0; max_dispersion = 0.0; + pulse_width = 0.0; ref_id = 0; max_lock_age = 2; lock_ref_id = 0; @@ -766,6 +767,9 @@ parse_refclock(char *line) } else if (!strcasecmp(cmd, "maxdispersion")) { if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1) break; + } else if (!strcasecmp(cmd, "width")) { + if (sscanf(line, "%lf%n", &pulse_width, &n) != 1) + break; } else if (!strcasecmp(cmd, "noselect")) { n = 0; sel_options |= SRC_SELECT_NOSELECT; @@ -804,6 +808,7 @@ parse_refclock(char *line) refclock->delay = delay; refclock->precision = precision; refclock->max_dispersion = max_dispersion; + refclock->pulse_width = pulse_width; refclock->ref_id = ref_id; refclock->max_lock_age = max_lock_age; refclock->lock_ref_id = lock_ref_id; diff --git a/refclock.c b/refclock.c index 0cdc061..e89b485 100644 --- a/refclock.c +++ b/refclock.c @@ -85,6 +85,7 @@ struct RCL_Instance_Record { double offset; double delay; double precision; + double pulse_width; SCH_TimeoutID timeout_id; SRC_Instance source; }; @@ -208,6 +209,7 @@ RCL_AddRefclock(RefclockParameters *params) inst->delay = params->delay; if (params->precision > 0.0) inst->precision = params->precision; + inst->pulse_width = params->pulse_width; inst->timeout_id = -1; inst->source = NULL; @@ -415,6 +417,27 @@ RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second) return RCL_AddCookedPulse(instance, &cooked_time, second, dispersion, correction); } +static int +check_pulse_edge(RCL_Instance instance, double offset, double distance) +{ + double max_error; + + if (instance->pulse_width <= 0.0) + return 1; + + max_error = 1.0 / instance->pps_rate - instance->pulse_width; + max_error = MIN(instance->pulse_width, max_error); + max_error *= 0.5; + + if (fabs(offset) > max_error || distance > max_error) { + DEBUG_LOG("refclock pulse ignored offset=%.9f distance=%.9f max_error=%.9f", + offset, distance, max_error); + return 0; + } + + return 1; +} + int RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time, double second, double dispersion, double raw_correction) @@ -476,6 +499,9 @@ RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time, return 0; } + if (!check_pulse_edge(instance, ref_offset - offset, 0.0)) + return 0; + leap = lock_refclock->leap_status; DEBUG_LOG("refclock pulse offset=%.9f offdiff=%.9f samplediff=%.9f", @@ -500,6 +526,9 @@ RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time, filter_reset(&instance->filter); return 0; } + + if (!check_pulse_edge(instance, offset, distance)) + return 0; } filter_add_sample(&instance->filter, cooked_time, offset, dispersion); diff --git a/refclock.h b/refclock.h index 0eb4caa..40ce12d 100644 --- a/refclock.h +++ b/refclock.h @@ -49,6 +49,7 @@ typedef struct { double delay; double precision; double max_dispersion; + double pulse_width; } RefclockParameters; typedef struct RCL_Instance_Record *RCL_Instance;