refclock: add option to filter wrong pulse edges
Add width option to the refclock directive to set expected width of pulses in a PPS signal. The width adds a limit for the maximum offset and root distance in order to reject PPS samples from wrong events, e.g. PHCs which cannot be configured to timestamp only rising of falling edges.
This commit is contained in:
parent
eceb8d9937
commit
1ca099473f
3 changed files with 36 additions and 1 deletions
7
conf.c
7
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;
|
||||
|
|
29
refclock.c
29
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);
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct {
|
|||
double delay;
|
||||
double precision;
|
||||
double max_dispersion;
|
||||
double pulse_width;
|
||||
} RefclockParameters;
|
||||
|
||||
typedef struct RCL_Instance_Record *RCL_Instance;
|
||||
|
|
Loading…
Reference in a new issue