@item precision
Refclock precision (in seconds). The default is 1e-6 (1 microsecond)
for SHM refclock, and 1e-9 (1 nanosecond) for SOCK, PPS and PHC refclocks.
+@item maxdispersion
+Maximum allowed dispersion for filtered samples (in seconds). Samples
+with larger estimated dispersion are ignored. By default, this limit
+is disabled.
@item prefer
Prefer this source over sources without prefer option.
@item noselect
{
int i, n, poll, dpoll, filter_length, pps_rate;
uint32_t ref_id, lock_ref_id;
- double offset, delay, precision;
+ double offset, delay, precision, max_dispersion;
char *p, *cmd, *name, *param;
unsigned char ref[5];
SRC_SelectOption sel_option;
offset = 0.0;
delay = 1e-9;
precision = 0.0;
+ max_dispersion = 0.0;
ref_id = 0;
lock_ref_id = 0;
sel_option = SRC_SelectNormal;
} else if (!strcasecmp(cmd, "precision")) {
if (sscanf(line, "%lf%n", &precision, &n) != 1)
break;
+ } else if (!strcasecmp(cmd, "maxdispersion")) {
+ if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1)
+ break;
} else if (!strcasecmp(cmd, "noselect")) {
n = 0;
sel_option = SRC_SelectNoselect;
refclock_sources[i].offset = offset;
refclock_sources[i].delay = delay;
refclock_sources[i].precision = precision;
+ refclock_sources[i].max_dispersion = max_dispersion;
refclock_sources[i].sel_option = sel_option;
refclock_sources[i].ref_id = ref_id;
refclock_sources[i].lock_ref_id = lock_ref_id;
int last;
int avg_var_n;
double avg_var;
+ double max_var;
struct FilterSample *samples;
int *selected;
double *x_data;
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 filter_init(struct MedianFilter *filter, int length);
+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);
return 0;
}
- filter_init(&inst->filter, params->filter_length);
+ filter_init(&inst->filter, params->filter_length, params->max_dispersion);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
}
static void
-filter_init(struct MedianFilter *filter, int length)
+filter_init(struct MedianFilter *filter, int length, double max_dispersion)
{
if (length < 1)
length = 1;
/* set first estimate to system precision */
filter->avg_var_n = 0;
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
+ filter->max_var = max_dispersion * max_dispersion;
filter->samples = MallocArray(struct FilterSample, filter->length);
filter->selected = MallocArray(int, filter->length);
filter->x_data = MallocArray(double, filter->length);
d = sqrt(var);
}
+ /* drop the sample if variance is larger than allowed maximum */
+ if (filter->max_var > 0.0 && var > filter->max_var) {
+ DEBUG_LOG(LOGF_Refclock, "filter dispersion too large disp=%.9f max=%.9f",
+ sqrt(var), sqrt(filter->max_var));
+ return 0;
+ }
+
prev_avg_var = filter->avg_var;
/* update exponential moving average of the variance */