Add modular filter interface.
Similarly to the servo interface, allow multiple filters to be used for delay filtering. Convert mave to the new interface. Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>master
parent
7bd59737d3
commit
2c9718f3c2
16
clock.c
16
clock.c
|
@ -27,7 +27,7 @@
|
||||||
#include "clockadj.h"
|
#include "clockadj.h"
|
||||||
#include "clockcheck.h"
|
#include "clockcheck.h"
|
||||||
#include "foreign.h"
|
#include "foreign.h"
|
||||||
#include "mave.h"
|
#include "filter.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "phc.h"
|
#include "phc.h"
|
||||||
|
@ -86,7 +86,7 @@ struct clock {
|
||||||
enum servo_state servo_state;
|
enum servo_state servo_state;
|
||||||
tmv_t master_offset;
|
tmv_t master_offset;
|
||||||
tmv_t path_delay;
|
tmv_t path_delay;
|
||||||
struct mave *avg_delay;
|
struct filter *delay_filter;
|
||||||
struct freq_estimator fest;
|
struct freq_estimator fest;
|
||||||
struct time_status_np status;
|
struct time_status_np status;
|
||||||
double nrr;
|
double nrr;
|
||||||
|
@ -121,7 +121,7 @@ void clock_destroy(struct clock *c)
|
||||||
phc_close(c->clkid);
|
phc_close(c->clkid);
|
||||||
}
|
}
|
||||||
servo_destroy(c->servo);
|
servo_destroy(c->servo);
|
||||||
mave_destroy(c->avg_delay);
|
filter_destroy(c->delay_filter);
|
||||||
stats_destroy(c->stats.offset);
|
stats_destroy(c->stats.offset);
|
||||||
stats_destroy(c->stats.freq);
|
stats_destroy(c->stats.freq);
|
||||||
stats_destroy(c->stats.delay);
|
stats_destroy(c->stats.delay);
|
||||||
|
@ -632,9 +632,9 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
c->servo_state = SERVO_UNLOCKED;
|
c->servo_state = SERVO_UNLOCKED;
|
||||||
c->avg_delay = mave_create(MAVE_LENGTH);
|
c->delay_filter = filter_create(FILTER_MOVING_AVERAGE, MAVE_LENGTH);
|
||||||
if (!c->avg_delay) {
|
if (!c->delay_filter) {
|
||||||
pr_err("Failed to create moving average");
|
pr_err("Failed to create delay filter");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
c->stats_interval = dds->stats_interval;
|
c->stats_interval = dds->stats_interval;
|
||||||
|
@ -992,7 +992,7 @@ void clock_path_delay(struct clock *c, struct timespec req, struct timestamp rx,
|
||||||
pr_warning("c3 %10lld", c3);
|
pr_warning("c3 %10lld", c3);
|
||||||
}
|
}
|
||||||
|
|
||||||
c->path_delay = mave_accumulate(c->avg_delay, pd);
|
c->path_delay = filter_sample(c->delay_filter, pd);
|
||||||
|
|
||||||
c->cur.meanPathDelay = tmv_to_TimeInterval(c->path_delay);
|
c->cur.meanPathDelay = tmv_to_TimeInterval(c->path_delay);
|
||||||
|
|
||||||
|
@ -1170,7 +1170,7 @@ static void handle_state_decision_event(struct clock *c)
|
||||||
|
|
||||||
if (!cid_eq(&best_id, &c->best_id)) {
|
if (!cid_eq(&best_id, &c->best_id)) {
|
||||||
clock_freq_est_reset(c);
|
clock_freq_est_reset(c);
|
||||||
mave_reset(c->avg_delay);
|
filter_reset(c->delay_filter);
|
||||||
c->t1 = tmv_zero();
|
c->t1 = tmv_zero();
|
||||||
c->t2 = tmv_zero();
|
c->t2 = tmv_zero();
|
||||||
c->path_delay = 0;
|
c->path_delay = 0;
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* @file filter.c
|
||||||
|
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "filter_private.h"
|
||||||
|
#include "mave.h"
|
||||||
|
|
||||||
|
struct filter *filter_create(enum filter_type type, int length)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case FILTER_MOVING_AVERAGE:
|
||||||
|
return mave_create(length);
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void filter_destroy(struct filter *filter)
|
||||||
|
{
|
||||||
|
filter->destroy(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmv_t filter_sample(struct filter *filter, tmv_t sample)
|
||||||
|
{
|
||||||
|
return filter->sample(filter, sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void filter_reset(struct filter *filter)
|
||||||
|
{
|
||||||
|
filter->reset(filter);
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* @file filter.h
|
||||||
|
* @brief Implements a generic filter interface.
|
||||||
|
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_FILTER_H
|
||||||
|
#define HAVE_FILTER_H
|
||||||
|
|
||||||
|
#include "tmv.h"
|
||||||
|
|
||||||
|
/** Opaque type */
|
||||||
|
struct filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the available filters.
|
||||||
|
*/
|
||||||
|
enum filter_type {
|
||||||
|
FILTER_MOVING_AVERAGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of a filter.
|
||||||
|
* @param type The type of the filter to create.
|
||||||
|
* @param length The filter's length.
|
||||||
|
* @return A pointer to a new filter on success, NULL otherwise.
|
||||||
|
*/
|
||||||
|
struct filter *filter_create(enum filter_type type, int length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an instance of a filter.
|
||||||
|
* @param filter Pointer to a filter obtained via @ref filter_create().
|
||||||
|
*/
|
||||||
|
void filter_destroy(struct filter *filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feed a sample into a filter.
|
||||||
|
* @param filter Pointer to a filter obtained via @ref filter_create().
|
||||||
|
* @param sample The input sample.
|
||||||
|
* @return The output value.
|
||||||
|
*/
|
||||||
|
tmv_t filter_sample(struct filter *filter, tmv_t sample);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset a filter.
|
||||||
|
* @param filter Pointer to a filter obtained via @ref filter_create().
|
||||||
|
*/
|
||||||
|
void filter_reset(struct filter *filter);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* @file filter_private.h
|
||||||
|
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_FILTER_PRIVATE_H
|
||||||
|
#define HAVE_FILTER_PRIVATE_H
|
||||||
|
|
||||||
|
#include "tmv.h"
|
||||||
|
#include "contain.h"
|
||||||
|
|
||||||
|
struct filter {
|
||||||
|
void (*destroy)(struct filter *filter);
|
||||||
|
|
||||||
|
tmv_t (*sample)(struct filter *filter, tmv_t sample);
|
||||||
|
|
||||||
|
void (*reset)(struct filter *filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
5
makefile
5
makefile
|
@ -24,8 +24,9 @@ CFLAGS = -Wall $(VER) $(incdefs) $(DEBUG) $(EXTRA_CFLAGS)
|
||||||
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
|
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
|
||||||
PRG = ptp4l pmc phc2sys hwstamp_ctl
|
PRG = ptp4l pmc phc2sys hwstamp_ctl
|
||||||
OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o fault.o \
|
OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o fault.o \
|
||||||
fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o print.o raw.o servo.o \
|
filter.o fsm.o mave.o msg.o phc.o pi.o port.o print.o \
|
||||||
sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o uds.o util.o version.o
|
ptp4l.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o \
|
||||||
|
udp6.o uds.o util.o version.o
|
||||||
|
|
||||||
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
|
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
|
||||||
SRC = $(OBJECTS:.o=.c)
|
SRC = $(OBJECTS:.o=.c)
|
||||||
|
|
48
mave.c
48
mave.c
|
@ -20,8 +20,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "mave.h"
|
#include "mave.h"
|
||||||
|
#include "filter_private.h"
|
||||||
|
|
||||||
struct mave {
|
struct mave {
|
||||||
|
struct filter filter;
|
||||||
int cnt;
|
int cnt;
|
||||||
int len;
|
int len;
|
||||||
int index;
|
int index;
|
||||||
|
@ -29,30 +31,17 @@ struct mave {
|
||||||
tmv_t *val;
|
tmv_t *val;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mave *mave_create(int length)
|
static void mave_destroy(struct filter *filter)
|
||||||
{
|
|
||||||
struct mave *m;
|
|
||||||
m = calloc(1, sizeof(*m));
|
|
||||||
if (!m) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m->val = calloc(1, length * sizeof(*m->val));
|
|
||||||
if (!m->val) {
|
|
||||||
free(m);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m->len = length;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mave_destroy(struct mave *m)
|
|
||||||
{
|
{
|
||||||
|
struct mave *m = container_of(filter, struct mave, filter);
|
||||||
free(m->val);
|
free(m->val);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmv_t mave_accumulate(struct mave *m, tmv_t val)
|
static tmv_t mave_accumulate(struct filter *filter, tmv_t val)
|
||||||
{
|
{
|
||||||
|
struct mave *m = container_of(filter, struct mave, filter);
|
||||||
|
|
||||||
m->sum = tmv_sub(m->sum, m->val[m->index]);
|
m->sum = tmv_sub(m->sum, m->val[m->index]);
|
||||||
m->val[m->index] = val;
|
m->val[m->index] = val;
|
||||||
m->index = (1 + m->index) % m->len;
|
m->index = (1 + m->index) % m->len;
|
||||||
|
@ -63,10 +52,31 @@ tmv_t mave_accumulate(struct mave *m, tmv_t val)
|
||||||
return tmv_div(m->sum, m->cnt);
|
return tmv_div(m->sum, m->cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mave_reset(struct mave *m)
|
static void mave_reset(struct filter *filter)
|
||||||
{
|
{
|
||||||
|
struct mave *m = container_of(filter, struct mave, filter);
|
||||||
|
|
||||||
m->cnt = 0;
|
m->cnt = 0;
|
||||||
m->index = 0;
|
m->index = 0;
|
||||||
m->sum = 0;
|
m->sum = 0;
|
||||||
memset(m->val, 0, m->len * sizeof(*m->val));
|
memset(m->val, 0, m->len * sizeof(*m->val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct filter *mave_create(int length)
|
||||||
|
{
|
||||||
|
struct mave *m;
|
||||||
|
m = calloc(1, sizeof(*m));
|
||||||
|
if (!m) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m->filter.destroy = mave_destroy;
|
||||||
|
m->filter.sample = mave_accumulate;
|
||||||
|
m->filter.reset = mave_reset;
|
||||||
|
m->val = calloc(1, length * sizeof(*m->val));
|
||||||
|
if (!m->val) {
|
||||||
|
free(m);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m->len = length;
|
||||||
|
return &m->filter;
|
||||||
|
}
|
||||||
|
|
12
mave.h
12
mave.h
|
@ -20,16 +20,8 @@
|
||||||
#ifndef HAVE_MAVE_H
|
#ifndef HAVE_MAVE_H
|
||||||
#define HAVE_MAVE_H
|
#define HAVE_MAVE_H
|
||||||
|
|
||||||
#include "tmv.h"
|
#include "filter.h"
|
||||||
|
|
||||||
struct mave;
|
struct filter *mave_create(int length);
|
||||||
|
|
||||||
struct mave *mave_create(int length);
|
|
||||||
|
|
||||||
void mave_destroy(struct mave *m);
|
|
||||||
|
|
||||||
tmv_t mave_accumulate(struct mave *m, tmv_t val);
|
|
||||||
|
|
||||||
void mave_reset(struct mave *m);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
14
port.c
14
port.c
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include "bmc.h"
|
#include "bmc.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "mave.h"
|
#include "filter.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
@ -82,7 +82,7 @@ struct port {
|
||||||
} seqnum;
|
} seqnum;
|
||||||
struct tmtab tmtab;
|
struct tmtab tmtab;
|
||||||
tmv_t peer_delay;
|
tmv_t peer_delay;
|
||||||
struct mave *avg_delay;
|
struct filter *delay_filter;
|
||||||
int log_sync_interval;
|
int log_sync_interval;
|
||||||
struct nrate_estimator nrate;
|
struct nrate_estimator nrate;
|
||||||
unsigned int pdr_missing;
|
unsigned int pdr_missing;
|
||||||
|
@ -1716,7 +1716,7 @@ calc:
|
||||||
pd = tmv_sub(pd, c2);
|
pd = tmv_sub(pd, c2);
|
||||||
pd = tmv_div(pd, 2);
|
pd = tmv_div(pd, 2);
|
||||||
|
|
||||||
p->peer_delay = mave_accumulate(p->avg_delay, pd);
|
p->peer_delay = filter_sample(p->delay_filter, pd);
|
||||||
|
|
||||||
p->peerMeanPathDelay = tmv_to_TimeInterval(p->peer_delay);
|
p->peerMeanPathDelay = tmv_to_TimeInterval(p->peer_delay);
|
||||||
|
|
||||||
|
@ -1845,7 +1845,7 @@ void port_close(struct port *p)
|
||||||
port_disable(p);
|
port_disable(p);
|
||||||
}
|
}
|
||||||
transport_destroy(p->trp);
|
transport_destroy(p->trp);
|
||||||
mave_destroy(p->avg_delay);
|
filter_destroy(p->delay_filter);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2306,9 +2306,9 @@ struct port *port_open(int phc_index,
|
||||||
p->delayMechanism = interface->dm;
|
p->delayMechanism = interface->dm;
|
||||||
p->versionNumber = PTP_VERSION;
|
p->versionNumber = PTP_VERSION;
|
||||||
|
|
||||||
p->avg_delay = mave_create(PORT_MAVE_LENGTH);
|
p->delay_filter = filter_create(FILTER_MOVING_AVERAGE, PORT_MAVE_LENGTH);
|
||||||
if (!p->avg_delay) {
|
if (!p->delay_filter) {
|
||||||
pr_err("Failed to create moving average");
|
pr_err("Failed to create delay filter");
|
||||||
transport_destroy(p->trp);
|
transport_destroy(p->trp);
|
||||||
free(p);
|
free(p);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue