]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Adjust refclock filter parameters
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 24 Feb 2010 11:02:53 +0000 (12:02 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 2 Mar 2010 12:19:33 +0000 (13:19 +0100)
Drop only about 40 percent of samples, change default length to 64,
require at least 4 samples between polls (or full filter for lengths
below 4).

chrony.texi
conf.c
refclock.c

index 60f2924b39dc9f1d59e77a545199072bd0dd38d1..be6b946850b349498ca98778bc4b939ea1c37af5 100644 (file)
@@ -2287,9 +2287,11 @@ driver name and the number of the refclock are used as refid.  Each
 refclock has to use an unique refid.
 @item filter
 This option sets the length of the median filter which is used to
-reduce noise.  With each poll about half of the stored samples are
+reduce noise.  With each poll about 40 percent of the stored samples is
 discarded and one final sample is calculated as average of the
-remaining samples.  The default is 15.
+remaining samples.  If the length is 4 or above, at least 4 samples
+have to be collected between polls.  For lengths below 4, the filter
+has to be full.  The default is 64.
 @item rate
 PPS signal frequency (in Hz).  This option only controls how the
 received pulses are aligned.  To actually receive more than one
diff --git a/conf.c b/conf.c
index 88a65255be132a0f505f0a464bf3d3fc3a9ccc9e..359c108c21961b32aa80c7c83ff4c3ce8a42baff 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -448,7 +448,7 @@ parse_refclock(const char *line)
 
   poll = 4;
   dpoll = 0;
-  filter_length = 15;
+  filter_length = 64;
   pps_rate = 0;
   offset = 0.0;
   delay = 1e-9;
index 54e72bafdae25e089dd107e5ba7d98b64bc2f5cb..ad7cde97ba7ec583c2a846792e556f8d484d3bbb 100644 (file)
@@ -210,9 +210,6 @@ RCL_AddRefclock(RefclockParameters *params)
     inst->pps_rate = 0;
   }
 
-  if (inst->driver_poll > inst->poll)
-    inst->driver_poll = inst->poll;
-
   if (params->ref_id)
     inst->ref_id = params->ref_id;
   else {
@@ -222,6 +219,22 @@ RCL_AddRefclock(RefclockParameters *params)
     inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
   }
 
+  if (inst->driver->poll) {
+    int max_samples;
+
+    if (inst->driver_poll > inst->poll)
+      inst->driver_poll = inst->poll;
+
+    max_samples = 1 << (inst->poll - inst->driver_poll);
+    if (max_samples < params->filter_length) {
+      if (max_samples < 4) {
+        LOG(LOGS_WARN, LOGF_Refclock, "Setting filter length for %s to %d",
+            UTI_RefidToString(inst->ref_id), max_samples);
+      }
+      params->filter_length = max_samples;
+    }
+  }
+
   if (inst->driver->init)
     if (!inst->driver->init(inst)) {
       LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
@@ -691,28 +704,46 @@ filter_select_samples(struct MedianFilter *filter)
   if (filter->used < 1)
     return 0;
 
+  /* for lengths below 4 require full filter,
+     for 4 and above require at least 4 samples */
+  if ((filter->length < 4 && filter->used != filter->length) ||
+      (filter->length >= 4 && filter->used < 4))
+    return 0;
+
   selected = filter->selected;
 
-  for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
-    if (min_dispersion > filter->samples[i].dispersion)
-      min_dispersion = filter->samples[i].dispersion;
-  }
+  if (filter->used > 4) {
+    /* select samples with dispersion better than 1.5 * minimum */
 
-  /* select samples with dispersion better than 1.5 * minimum */
-  for (i = j = 0; i < filter->used; i++) {
-    if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
-      selected[j++] = i;
+    for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
+      if (min_dispersion > filter->samples[i].dispersion)
+        min_dispersion = filter->samples[i].dispersion;
+    }
+
+    for (i = j = 0; i < filter->used; i++) {
+      if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
+        selected[j++] = i;
+    }
+  } else {
+    j = 0;
   }
 
-  assert(j > 0);
+  if (j < 4) {
+    /* select all samples */
+
+    for (j = 0; j < filter->used; j++)
+      selected[j] = j;
+  }
 
   /* and sort their indices by offset */
   tmp_sorted_array = filter->samples;
   qsort(selected, j, sizeof (int), sample_compare);
 
-  /* select half of the samples closest to the median */ 
+  /* select 60 percent of the samples closest to the median */ 
   if (j > 2) {
-    from = (j + 2) / 4;
+    from = j / 5;
+    if (from < 1)
+      from = 1;
     to = j - from;
   } else {
     from = 0;