1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/src/signal.c

167 lines
4 KiB
C
Raw Normal View History

/** Generate random packages on stdout.
*
* @file
2015-06-02 21:53:04 +02:00
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
2015-06-02 21:53:04 +02:00
*
* @addtogroup tools Test and debug tools
* @{
2015-06-02 21:53:04 +02:00
**********************************************************************************/
#include <unistd.h>
#include <math.h>
#include <string.h>
#include "config.h"
#include "utils.h"
2016-06-08 22:38:21 +02:00
#include "sample.h"
2015-06-02 22:06:15 +02:00
#include "timing.h"
#define CLOCKID CLOCK_REALTIME
enum SIGNAL_TYPE {
TYPE_RANDOM,
TYPE_SINE,
TYPE_SQUARE,
TYPE_TRIANGLE,
TYPE_RAMP,
TYPE_MIXED
};
void usage(char *name)
{
printf("Usage: %s SIGNAL [OPTIONS]\n", name);
printf(" SIGNAL is on of: 'mixed', 'random', 'sine', 'triangle', 'square', 'ramp'\n");
printf(" -v NUM specifies how many values a message should contain\n");
printf(" -r HZ how many messages per second\n");
printf(" -f HZ the frequency of the signal\n");
printf(" -a FLT the amplitude\n");
printf(" -d FLT the standard deviation for 'random' signals\n");
printf(" -l NUM only send LIMIT messages and stop\n\n");
print_copyright();
}
int main(int argc, char *argv[])
{
2017-03-03 20:21:33 -04:00
struct log log;
/* Some default values */
double rate = 10;
double freq = 1;
double ampl = 1;
double stddev = 0.02;
int type = TYPE_MIXED;
int values = 1;
int limit = -1;
2016-06-08 22:36:38 +02:00
int counter;
2016-06-26 15:32:37 +02:00
2017-03-03 20:21:33 -04:00
log_init(&log);
2015-03-21 18:03:55 +01:00
if (argc < 2) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
/* Parse signal type */
if (!strcmp(argv[1], "random"))
type = TYPE_RANDOM;
else if (!strcmp(argv[1], "sine"))
type = TYPE_SINE;
else if (!strcmp(argv[1], "square"))
type = TYPE_SQUARE;
else if (!strcmp(argv[1], "triangle"))
type = TYPE_TRIANGLE;
else if (!strcmp(argv[1], "ramp"))
type = TYPE_RAMP;
else if (!strcmp(argv[1], "mixed"))
type = TYPE_MIXED;
/* Parse optional command line arguments */
char c, *endptr;
while ((c = getopt(argc-1, argv+1, "hv:r:f:l:a:d:")) != -1) {
switch (c) {
case 'l':
limit = strtoul(optarg, &endptr, 10);
goto check;
case 'v':
values = strtoul(optarg, &endptr, 10);
goto check;
case 'r':
rate = strtof(optarg, &endptr);
goto check;
case 'f':
freq = strtof(optarg, &endptr);
goto check;
case 'a':
ampl = strtof(optarg, &endptr);
goto check;
case 'd':
stddev = strtof(optarg, &endptr);
goto check;
case 'h':
case '?':
usage(argv[0]);
}
continue;
check: if (optarg == endptr)
error("Failed to parse parse option argument '-%c %s'", c, optarg);
}
/* Allocate memory for message buffer */
2016-06-08 22:38:21 +02:00
struct sample *s = alloc(SAMPLE_LEN(values));
/* Print header */
2016-06-08 23:21:42 +02:00
printf("# VILLASnode signal params: type=%s, values=%u, rate=%f, limit=%d, amplitude=%f, freq=%f\n",
argv[1], values, rate, limit, ampl, freq);
printf("# %-20s\t\t%s\n", "sec.nsec(seq)", "data[]");
/* Setup timer */
2016-01-14 22:57:39 +01:00
int tfd = timerfd_create_rate(rate);
if (tfd < 0)
serror("Failed to create timer");
struct timespec start = time_now();
2015-06-02 22:43:57 +02:00
2016-06-08 22:36:38 +02:00
counter = 0;
while (limit < 0 || counter < limit) {
struct timespec now = time_now();
double running = time_delta(&start, &now);
2016-06-08 22:38:21 +02:00
s->ts.origin = now;
s->sequence = counter;
s->length = values;
2016-06-08 22:38:21 +02:00
for (int i = 0; i < values; i++) {
int rtype = (type != TYPE_MIXED) ? type : i % 4;
switch (rtype) {
case TYPE_RANDOM: s->data[i].f += box_muller(0, stddev); break;
case TYPE_SINE: s->data[i].f = ampl * sin(running * freq * 2 * M_PI); break;
case TYPE_TRIANGLE: s->data[i].f = ampl * (fabs(fmod(running * freq, 1) - .5) - 0.25) * 4; break;
case TYPE_SQUARE: s->data[i].f = ampl * ( (fmod(running * freq, 1) < .5) ? -1 : 1); break;
case TYPE_RAMP: s->data[i].f = fmod(counter, rate / freq); /** @todo send as integer? */ break;
}
}
2016-06-08 22:38:21 +02:00
sample_fprint(stdout, s, SAMPLE_ALL & ~SAMPLE_OFFSET);
fflush(stdout);
/* Block until 1/p->rate seconds elapsed */
2016-06-08 22:38:21 +02:00
int steps = timerfd_wait(tfd);
if (steps > 1)
warn("Missed steps: %u", steps);
counter += steps;
}
close(tfd);
2016-06-08 22:38:21 +02:00
free(s);
return 0;
}
2015-08-07 01:11:43 +02:00
/** @} */