mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
hooks: rewrite a bunch of hooks to the new signal list method
This commit is contained in:
parent
df6317d593
commit
4229531cf1
6 changed files with 361 additions and 164 deletions
|
@ -33,7 +33,7 @@ set(HOOK_SRC
|
|||
limit_rate.c
|
||||
scale.c
|
||||
fix.c
|
||||
# cast.c
|
||||
cast.c
|
||||
average.c
|
||||
dump.c
|
||||
dp.c
|
||||
|
|
|
@ -29,43 +29,129 @@
|
|||
#include <villas/hook.h>
|
||||
#include <villas/plugin.h>
|
||||
#include <villas/sample.h>
|
||||
#include <villas/bitset.h>
|
||||
|
||||
struct average {
|
||||
int mask;
|
||||
int offset;
|
||||
|
||||
struct bitset mask;
|
||||
struct vlist signal_names;
|
||||
};
|
||||
|
||||
static int average_init(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct average *a = (struct average *) h->_vd;
|
||||
|
||||
ret = vlist_init(&a->signal_names);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bitset_init(&a->mask, 128);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bitset_clear_all(&a->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int average_destroy(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct average *a = (struct average *) h->_vd;
|
||||
|
||||
ret = vlist_destroy(&a->signal_names, NULL, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bitset_destroy(&a->mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int average_prepare(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct average *a = (struct average *) h->_vd;
|
||||
struct signal *avg_sig;
|
||||
|
||||
/* Setup mask */
|
||||
for (size_t i = 0; i < vlist_length(&a->signal_names); i++) {
|
||||
char *signal_name = (char *) vlist_at_safe(&a->signal_names, i);
|
||||
|
||||
int index = vlist_lookup_index(&a->signal_names, signal_name);
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
bitset_set(&a->mask, index);
|
||||
}
|
||||
|
||||
/* Add averaged signal */
|
||||
avg_sig = signal_create("average", NULL, SIGNAL_TYPE_FLOAT);
|
||||
if (!avg_sig)
|
||||
return -1;
|
||||
|
||||
ret = vlist_insert(&h->signals, a->offset, avg_sig);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int average_parse(struct hook *h, json_t *cfg)
|
||||
{
|
||||
struct average *p = (struct average *) h->_vd;
|
||||
struct average *a = (struct average *) h->_vd;
|
||||
|
||||
int ret;
|
||||
size_t i;
|
||||
json_error_t err;
|
||||
json_t *json_signals, *json_signal;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: i }",
|
||||
"offset", &p->offset,
|
||||
"mask", &p->mask
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: o }",
|
||||
"offset", &a->offset,
|
||||
"signals", &json_signals
|
||||
);
|
||||
if (ret)
|
||||
jerror(&err, "Failed to parse configuration of hook '%s'", hook_type_name(h->_vt));
|
||||
|
||||
if (!json_is_array(json_signals))
|
||||
error("Setting 'signals' of hook '%s' must be a list of signal names", hook_type_name(h->_vt));
|
||||
|
||||
json_array_foreach(json_signals, i, json_signal) {
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
vlist_push(&a->signal_names, strdup(json_string_value(json_signal)));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
bitset_set(&a->mask, json_integer_value(json_signal));
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Invalid value for setting 'signals' in hook '%s'", hook_type_name(h->_vt));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int average_process(struct hook *h, struct sample *smps[], unsigned *cnt)
|
||||
{
|
||||
struct average *p = (struct average *) h->_vd;
|
||||
struct average *a = (struct average *) h->_vd;
|
||||
|
||||
for (int i = 0; i < *cnt; i++) {
|
||||
struct sample *smp = smps[i];
|
||||
double sum = 0;
|
||||
double avg, sum = 0;
|
||||
int n = 0;
|
||||
|
||||
for (int k = 0; k < smp->length; k++) {
|
||||
if (!(p->mask & (1 << k)))
|
||||
if (!bitset_test(&a->mask, k))
|
||||
continue;
|
||||
|
||||
switch (sample_format(smps[i], k)) {
|
||||
switch (sample_format(smp, k)) {
|
||||
case SIGNAL_TYPE_INTEGER:
|
||||
sum += smp->data[k].i;
|
||||
break;
|
||||
|
@ -84,7 +170,9 @@ static int average_process(struct hook *h, struct sample *smps[], unsigned *cnt)
|
|||
n++;
|
||||
}
|
||||
|
||||
smp->data[p->offset].f = sum / n;
|
||||
avg = n == 0 ? 0 : sum / n;
|
||||
sample_data_insert(smp, (union signal_data *) &avg, a->offset, 1);
|
||||
smp->signals = &h->signals;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -99,6 +187,9 @@ static struct plugin p = {
|
|||
.priority = 99,
|
||||
.parse = average_parse,
|
||||
.process = average_process,
|
||||
.init = average_init,
|
||||
.init_signals = average_prepare,
|
||||
.destroy = average_destroy,
|
||||
.size = sizeof(struct average)
|
||||
}
|
||||
};
|
||||
|
|
129
lib/hooks/cast.c
129
lib/hooks/cast.c
|
@ -29,38 +29,58 @@
|
|||
|
||||
#include <villas/hook.h>
|
||||
#include <villas/plugin.h>
|
||||
#include <villas/node.h>
|
||||
#include <villas/path.h>
|
||||
#include <villas/sample.h>
|
||||
|
||||
struct cast {
|
||||
int index;
|
||||
int signal_index;
|
||||
char *signal_name;
|
||||
|
||||
enum signal_type new_type;
|
||||
char *new_name;
|
||||
char *new_unit;
|
||||
};
|
||||
|
||||
static int cast_init(struct hook *h)
|
||||
static int cast_prepare(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct signal *orig_sig, *new_sig;
|
||||
struct cast *c = (struct cast *) h->_vd;
|
||||
struct vlist *orig_signals;
|
||||
|
||||
if (h->node)
|
||||
orig_signals = &h->node->in.signals;
|
||||
else if (h->path)
|
||||
orig_signals = &h->path->signals;
|
||||
else
|
||||
return -1;
|
||||
if (c->signal_name) {
|
||||
c->signal_index = vlist_lookup_index(&h->signals, c->signal_name);
|
||||
if (c->signal_index < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct signal *orig_sig = vlist_at(orig_signals, i);
|
||||
struct signal *new_sig = signal_copy(orig_sig);
|
||||
char *name, *unit;
|
||||
enum signal_type type;
|
||||
|
||||
orig_sig = vlist_at_safe(&h->signals, c->signal_index);
|
||||
|
||||
type = c->new_type != SIGNAL_TYPE_AUTO ? c->new_type : orig_sig->type;
|
||||
name = c->new_name ? c->new_name : orig_sig->name;
|
||||
unit = c->new_unit ? c->new_unit : orig_sig->unit;
|
||||
|
||||
new_sig = signal_create(name, unit, type);
|
||||
|
||||
vlist_set(&h->signals, c->signal_index, new_sig);
|
||||
signal_decref(orig_sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cast_destroy(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct cast *c = (struct cast *) h->_vd;
|
||||
|
||||
if (c->signal_name)
|
||||
free(c->signal_name);
|
||||
|
||||
if (c->new_name)
|
||||
free(c->new_name);
|
||||
|
||||
if (c->new_unit)
|
||||
free(c->new_unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -68,67 +88,50 @@ static int cast_parse(struct hook *h, json_t *cfg)
|
|||
{
|
||||
int ret;
|
||||
struct cast *c = (struct cast *) h->_vd;
|
||||
struct signal *sig;
|
||||
|
||||
size_t i;
|
||||
json_error_t err;
|
||||
|
||||
int index = -1;
|
||||
const char *name = NULL;
|
||||
json_t *json_signal;
|
||||
|
||||
const char *new_name = NULL;
|
||||
const char *new_unit = NULL;
|
||||
const char *new_format = NULL;
|
||||
const char *new_type = NULL;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, "{ s?: s, s?: i, s?: s, s?: s, s?: s }",
|
||||
"name", &name,
|
||||
"index", &index,
|
||||
"new_format", &new_format,
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: o, s?: s, s?: s, s?: s }",
|
||||
"signal", &json_signal,
|
||||
"new_type", &new_type,
|
||||
"new_name", &new_name,
|
||||
"new_unit", &new_unit
|
||||
);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Find matching original signal descriptor */
|
||||
if (index >= 0 && name != NULL)
|
||||
return -1;
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
c->signal_name = strdup(json_string_value(json_signal));
|
||||
break;
|
||||
|
||||
if (index < 0 && name == NULL)
|
||||
return -1;
|
||||
case JSON_INTEGER:
|
||||
c->signal_name = NULL;
|
||||
c->signal_index = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
sig = name
|
||||
? vlist_lookup(&c->signals, name)
|
||||
: vlist_at_safe(&c->signals, index);
|
||||
if (!sig)
|
||||
return -1;
|
||||
default:
|
||||
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
|
||||
}
|
||||
|
||||
/* Cast to new format */
|
||||
if (new_format) {
|
||||
enum signal_type fmt;
|
||||
|
||||
fmt = signal_type_from_str(new_format);
|
||||
if (fmt == SIGNAL_TYPE_INVALID)
|
||||
if (new_type) {
|
||||
c->new_type = signal_type_from_str(new_type);
|
||||
if (c->new_type == SIGNAL_TYPE_INVALID)
|
||||
return -1;
|
||||
|
||||
sig->type = fmt;
|
||||
}
|
||||
else
|
||||
c->new_type = SIGNAL_TYPE_AUTO; // We use this constant to indicate that we dont want to change the type
|
||||
|
||||
/* Set new name */
|
||||
if (new_name) {
|
||||
if (sig->name)
|
||||
free(sig->name);
|
||||
if (new_name)
|
||||
c->new_name = strdup(new_name);
|
||||
|
||||
sig->name = strdup(new_name);
|
||||
}
|
||||
|
||||
/* Set new unit */
|
||||
if (new_unit) {
|
||||
if (sig->unit)
|
||||
free(sig->unit);
|
||||
|
||||
sig->unit = strdup(new_unit);
|
||||
}
|
||||
if (new_unit)
|
||||
c->new_unit = strdup(new_unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -140,15 +143,13 @@ static int cast_process(struct hook *h, struct sample *smps[], unsigned *cnt)
|
|||
for (int i = 0; i < *cnt; i++) {
|
||||
struct sample *smp = smps[i];
|
||||
|
||||
for (int j = 0; j < smp->length; j++) {
|
||||
struct signal *orig_sig = vlist_at(smp->signals, j);
|
||||
struct signal *new_sig = vlist_at(&c->signals, j);
|
||||
struct signal *orig_sig = vlist_at(smp->signals, c->signal_index);
|
||||
struct signal *new_sig = vlist_at(&h->signals, c->signal_index);
|
||||
|
||||
signal_data_cast(&smp->data[j], orig_sig, new_sig);
|
||||
}
|
||||
signal_data_cast(&smp->data[c->signal_index], orig_sig, new_sig);
|
||||
|
||||
/* Replace signal descriptors of sample */
|
||||
smp->signals = &c->signals;
|
||||
smp->signals = &h->signals;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -161,8 +162,8 @@ static struct plugin p = {
|
|||
.hook = {
|
||||
.flags = HOOK_NODE_READ | HOOK_PATH,
|
||||
.priority = 99,
|
||||
.init = cast_init,
|
||||
.destroy = cast_destroy,
|
||||
.init_signals = cast_prepare,
|
||||
.parse = cast_parse,
|
||||
.process = cast_process,
|
||||
.size = sizeof(struct cast)
|
||||
|
|
178
lib/hooks/dp.c
178
lib/hooks/dp.c
|
@ -36,7 +36,10 @@
|
|||
#define J _Complex_I
|
||||
|
||||
struct dp {
|
||||
int index;
|
||||
char *signal_name;
|
||||
int signal_index;
|
||||
|
||||
int offset;
|
||||
int inverse;
|
||||
|
||||
double f0;
|
||||
|
@ -48,30 +51,31 @@ struct dp {
|
|||
int fharmonics_len;
|
||||
|
||||
struct window window;
|
||||
|
||||
struct vlist *signals;
|
||||
};
|
||||
|
||||
static void dp_step(struct dp *d, double *in, float complex *out)
|
||||
{
|
||||
int n = d->window.steps;
|
||||
double r = 0.9999999999;
|
||||
double complex om, corr;
|
||||
double newest = *in;
|
||||
double oldest = window_update(&d->window, newest);
|
||||
|
||||
for (int i = 0; i < d->fharmonics_len; i++) {
|
||||
double pi_fharm = 2.0 * M_PI * d->fharmonics[i];
|
||||
om = 2.0 * M_PI * J * d->fharmonics[i] / n;
|
||||
|
||||
/* Recursive update */
|
||||
d->coeffs[i] = (d->coeffs[i] + (newest - oldest)) * cexp(pi_fharm);
|
||||
//d->coeffs[i] = cexp(om) * (d->coeffs[i] + (newest - oldest));
|
||||
d->coeffs[i] = d->coeffs[i] * r * cexp(om) - powf(r, n) * oldest + newest;
|
||||
|
||||
/* Correction for stationary phasor */
|
||||
double complex correction = cexp(pi_fharm * (d->t - (d->window.steps + 1)));
|
||||
double complex result = 2.0 / d->window.steps * d->coeffs[i] / correction;
|
||||
corr = cexp(-om * (d->t - (d->window.steps + 1)));
|
||||
|
||||
out[i] = (2.0 / d->window.steps) * (d->coeffs[i] * corr);
|
||||
|
||||
/* DC component */
|
||||
if (i == 0)
|
||||
result /= 2.0;
|
||||
|
||||
out[i] = result;
|
||||
if (d->fharmonics[i] == 0)
|
||||
out[i] /= 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +100,6 @@ static int dp_start(struct hook *h)
|
|||
struct dp *d = (struct dp *) h->_vd;
|
||||
|
||||
d->t = 0;
|
||||
d->signals = NULL;
|
||||
|
||||
for (int i = 0; i < d->fharmonics_len; i++)
|
||||
d->coeffs[i] = 0;
|
||||
|
@ -138,6 +141,9 @@ static int dp_destroy(struct hook *h)
|
|||
free(d->fharmonics);
|
||||
free(d->coeffs);
|
||||
|
||||
if (d->signal_name)
|
||||
free(d->signal_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -147,13 +153,13 @@ static int dp_parse(struct hook *h, json_t *cfg)
|
|||
|
||||
int ret;
|
||||
json_error_t err;
|
||||
json_t *json_harmonics, *json_harmonic;
|
||||
json_t *json_harmonics, *json_harmonic, *json_signal;
|
||||
size_t i;
|
||||
|
||||
double rate = -1, dt = -1;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: F, s?: F, s?: F, s: o, s?: b }",
|
||||
"index", &d->index,
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }",
|
||||
"signal", &json_signal,
|
||||
"f0", &d->f0,
|
||||
"dt", &dt,
|
||||
"rate", &rate,
|
||||
|
@ -173,6 +179,20 @@ static int dp_parse(struct hook *h, json_t *cfg)
|
|||
if (!json_is_array(json_harmonics))
|
||||
error("Setting 'harmonics' of hook '%s' must be a list of integers", plugin_name(h->_vt));
|
||||
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
d->signal_name = strdup(json_string_value(json_signal));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
d->signal_name = NULL;
|
||||
d->signal_index = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
|
||||
}
|
||||
|
||||
d->fharmonics_len = json_array_size(json_harmonics);
|
||||
d->fharmonics = alloc(d->fharmonics_len * sizeof(double));
|
||||
d->coeffs = alloc(d->fharmonics_len * sizeof(double complex));
|
||||
|
@ -183,7 +203,79 @@ static int dp_parse(struct hook *h, json_t *cfg)
|
|||
if (!json_is_integer(json_harmonic))
|
||||
error("Setting 'harmonics' of hook '%s' must be a list of integers", plugin_name(h->_vt));
|
||||
|
||||
d->fharmonics[i] = d->f0 * json_integer_value(json_harmonic);
|
||||
d->fharmonics[i] = json_integer_value(json_harmonic);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_prepare(struct hook *h)
|
||||
{
|
||||
int ret;
|
||||
struct dp *d = (struct dp *) h->_vd;
|
||||
|
||||
char *new_sig_name;
|
||||
struct signal *orig_sig, *new_sig;
|
||||
|
||||
if (d->signal_name) {
|
||||
d->signal_index = vlist_lookup_index(&h->signals, d->signal_name);
|
||||
if (d->signal_index < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (d->inverse) {
|
||||
/* Remove complex-valued coefficient signals */
|
||||
for (int i = 0; i < d->fharmonics_len; i++) {
|
||||
orig_sig = vlist_at_safe(&h->signals, d->signal_index + i);
|
||||
if (!orig_sig)
|
||||
return -1;
|
||||
|
||||
/** @todo: SIGNAL_TYPE_AUTO is bad here */
|
||||
if (orig_sig->type != SIGNAL_TYPE_COMPLEX && orig_sig->type != SIGNAL_TYPE_AUTO)
|
||||
return -1;
|
||||
|
||||
ret = vlist_remove(&h->signals, d->signal_index + i);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
signal_decref(orig_sig);
|
||||
}
|
||||
|
||||
/* Add new real-valued reconstructed signals */
|
||||
new_sig = signal_create("dp", "idp", SIGNAL_TYPE_FLOAT);
|
||||
if (!new_sig)
|
||||
return -1;
|
||||
|
||||
ret = vlist_insert(&h->signals, d->offset, new_sig);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
orig_sig = vlist_at_safe(&h->signals, d->signal_index);
|
||||
if (!orig_sig)
|
||||
return -1;
|
||||
|
||||
/** @todo: SIGNAL_TYPE_AUTO is bad here */
|
||||
if (orig_sig->type != SIGNAL_TYPE_FLOAT && orig_sig->type != SIGNAL_TYPE_AUTO)
|
||||
return -1;
|
||||
|
||||
ret = vlist_remove(&h->signals, d->signal_index);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < d->fharmonics_len; i++) {
|
||||
new_sig_name = strf("%s_harm%d", orig_sig->name, i);
|
||||
|
||||
new_sig = signal_create(new_sig_name, orig_sig->unit, SIGNAL_TYPE_COMPLEX);
|
||||
if (!new_sig)
|
||||
return -1;
|
||||
|
||||
ret = vlist_insert(&h->signals, d->offset + i, new_sig);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
signal_decref(orig_sig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -196,50 +288,29 @@ static int dp_process(struct hook *h, struct sample *smps[], unsigned *cnt)
|
|||
for (unsigned j = 0; j < *cnt; j++) {
|
||||
struct sample *smp = smps[j];
|
||||
|
||||
if (d->index > smp->length)
|
||||
if (d->signal_index > smp->length)
|
||||
continue;
|
||||
|
||||
if (!d->signals) {
|
||||
struct signal *orig_sig, *new_sig;
|
||||
if (d->inverse) {
|
||||
double signal;
|
||||
float complex *coeffs = &smp->data[d->signal_index].z;
|
||||
|
||||
d->signals = alloc(sizeof(struct vlist));
|
||||
d->signals->state = STATE_DESTROYED;
|
||||
dp_istep(d, coeffs, &signal);
|
||||
|
||||
vlist_copy(d->signals, smp->signals);
|
||||
sample_data_remove(smp, d->signal_index, d->fharmonics_len);
|
||||
sample_data_insert(smp, (union signal_data *) &signal, d->offset, 1);
|
||||
}
|
||||
else {
|
||||
double signal = smp->data[d->signal_index].f;
|
||||
float complex coeffs[d->fharmonics_len];
|
||||
|
||||
orig_sig = vlist_at(smp->signals, d->index);
|
||||
if (!orig_sig)
|
||||
return -1;
|
||||
dp_step(d, &signal, coeffs);
|
||||
|
||||
if (d->inverse) {
|
||||
if (orig_sig->type != SIGNAL_TYPE_COMPLEX)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (orig_sig->type != SIGNAL_TYPE_FLOAT)
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_sig = signal_copy(orig_sig);
|
||||
if (!new_sig)
|
||||
return -1;
|
||||
|
||||
if (d->inverse)
|
||||
new_sig->type = SIGNAL_TYPE_FLOAT;
|
||||
else
|
||||
new_sig->type = SIGNAL_TYPE_COMPLEX;
|
||||
|
||||
int ret = vlist_set(d->signals, d->index, new_sig);
|
||||
if (ret)
|
||||
return ret;
|
||||
sample_data_remove(smp, d->signal_index, 1);
|
||||
sample_data_insert(smp, (union signal_data *) coeffs, d->offset, d->fharmonics_len);
|
||||
}
|
||||
|
||||
smp->signals = d->signals;
|
||||
|
||||
if (d->inverse)
|
||||
dp_istep(d, &smp->data[d->index].z, &smp->data[d->index].f);
|
||||
else
|
||||
dp_step(d, &smp->data[d->index].f, &smp->data[d->index].z);
|
||||
smp->signals = &h->signals;
|
||||
}
|
||||
|
||||
d->t += d->dt;
|
||||
|
@ -252,9 +323,10 @@ static struct plugin p = {
|
|||
.description = "Transform to/from dynamic phasor domain",
|
||||
.type = PLUGIN_TYPE_HOOK,
|
||||
.hook = {
|
||||
.flags = HOOK_PATH,
|
||||
.flags = HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
|
||||
.priority = 99,
|
||||
.init = dp_init,
|
||||
.init_signals = dp_prepare,
|
||||
.destroy = dp_destroy,
|
||||
.start = dp_start,
|
||||
.stop = dp_stop,
|
||||
|
|
|
@ -56,18 +56,7 @@ static int print_start(struct hook *h)
|
|||
struct print *p = (struct print *) h->_vd;
|
||||
int ret;
|
||||
|
||||
struct vlist *signals;
|
||||
|
||||
if (h->node)
|
||||
signals = &h->node->in.signals;
|
||||
else if (h->path)
|
||||
signals = &h->path->signals;
|
||||
else
|
||||
signals = NULL;
|
||||
|
||||
ret = signals
|
||||
? io_init(&p->io, p->format, signals, SAMPLE_HAS_ALL)
|
||||
: io_init_auto(&p->io, p->format, DEFAULT_SAMPLE_LENGTH, SAMPLE_HAS_ALL);
|
||||
ret = io_init(&p->io, p->format, &h->signals, SAMPLE_HAS_ALL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -31,63 +31,105 @@
|
|||
#include <villas/sample.h>
|
||||
|
||||
struct scale {
|
||||
char *signal_name;
|
||||
int signal_index;
|
||||
|
||||
double scale;
|
||||
double offset;
|
||||
};
|
||||
|
||||
static int scale_init(struct hook *h)
|
||||
{
|
||||
struct scale *p = (struct scale *) h->_vd;
|
||||
struct scale *s = (struct scale *) h->_vd;
|
||||
|
||||
p->scale = 1;
|
||||
p->offset = 0;
|
||||
s->scale = 1;
|
||||
s->offset = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_prepare(struct hook *h)
|
||||
{
|
||||
struct scale *s = (struct scale *) h->_vd;
|
||||
|
||||
if (s->signal_name) {
|
||||
s->signal_index = vlist_lookup_index(&h->signals, s->signal_name);
|
||||
if (s->signal_index < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_destroy(struct hook *h)
|
||||
{
|
||||
struct scale *s = (struct scale *) h->_vd;
|
||||
|
||||
if (s->signal_name)
|
||||
free(s->signal_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_parse(struct hook *h, json_t *cfg)
|
||||
{
|
||||
struct scale *p = (struct scale *) h->_vd;
|
||||
struct scale *s = (struct scale *) h->_vd;
|
||||
|
||||
int ret;
|
||||
json_t *json_signal;
|
||||
json_error_t err;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s?: F, s?: F }",
|
||||
"scale", &p->scale,
|
||||
"offset", &p->offset
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s?: F, s?: F, s: o }",
|
||||
"scale", &s->scale,
|
||||
"offset", &s->offset,
|
||||
"signal", &json_signal
|
||||
);
|
||||
if (ret)
|
||||
jerror(&err, "Failed to parse configuration of hook '%s'", hook_type_name(h->_vt));
|
||||
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
s->signal_name = strdup(json_string_value(json_signal));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
s->signal_name = NULL;
|
||||
s->signal_index = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_process(struct hook *h, struct sample *smps[], unsigned *cnt)
|
||||
{
|
||||
struct scale *p = (struct scale *) h->_vd;
|
||||
struct scale *s = (struct scale *) h->_vd;
|
||||
|
||||
for (int i = 0; i < *cnt; i++) {
|
||||
for (int k = 0; k < smps[i]->length; k++) {
|
||||
struct sample *smp = smps[i];
|
||||
int k = s->signal_index;
|
||||
|
||||
switch (sample_format(smps[i], k)) {
|
||||
case SIGNAL_TYPE_INTEGER:
|
||||
smps[i]->data[k].i = smps[i]->data[k].i * p->scale + p->offset;
|
||||
break;
|
||||
switch (sample_format(smp, k)) {
|
||||
case SIGNAL_TYPE_INTEGER:
|
||||
smp->data[k].i = smp->data[k].i * s->scale + s->offset;
|
||||
break;
|
||||
|
||||
case SIGNAL_TYPE_FLOAT:
|
||||
smps[i]->data[k].f = smps[i]->data[k].f * p->scale + p->offset;
|
||||
break;
|
||||
case SIGNAL_TYPE_FLOAT:
|
||||
smp->data[k].f = smp->data[k].f * s->scale + s->offset;
|
||||
break;
|
||||
|
||||
case SIGNAL_TYPE_COMPLEX:
|
||||
smps[i]->data[k].z = smps[i]->data[k].z * p->scale + p->offset;
|
||||
break;
|
||||
case SIGNAL_TYPE_COMPLEX:
|
||||
smp->data[k].z = smp->data[k].z * s->scale + s->offset;
|
||||
break;
|
||||
|
||||
case SIGNAL_TYPE_BOOLEAN:
|
||||
smps[i]->data[k].b = smps[i]->data[k].b * p->scale + p->offset;
|
||||
break;
|
||||
case SIGNAL_TYPE_BOOLEAN:
|
||||
smp->data[k].b = smp->data[k].b * s->scale + s->offset;
|
||||
break;
|
||||
|
||||
default: { }
|
||||
}
|
||||
default: { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +144,8 @@ static struct plugin p = {
|
|||
.flags = HOOK_PATH,
|
||||
.priority = 99,
|
||||
.init = scale_init,
|
||||
.init_signals = scale_prepare,
|
||||
.destroy = scale_destroy,
|
||||
.parse = scale_parse,
|
||||
.process = scale_process,
|
||||
.size = sizeof(struct scale)
|
||||
|
|
Loading…
Add table
Reference in a new issue