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
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 {
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);
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;