sr: add new analog output module
This outputs text representation of SR_DF_ANALOG packets. Unlike the float module however, it also outputs the standard abbreviations of SI units corresponding to the packet's MQ and unit. It also makes an effort to multiply or divide the floating point value as needed to the nearest multiple or fraction, and inserts the appropriate SI prefix to match.
This commit is contained in:
parent
e6b021f377
commit
161a8a2726
|
@ -30,6 +30,7 @@ libsigrokoutput_la_SOURCES = \
|
|||
chronovu_la8.c \
|
||||
csv.c \
|
||||
float.c \
|
||||
analog.c \
|
||||
output.c
|
||||
|
||||
libsigrokoutput_la_CFLAGS = \
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* This file is part of the sigrok project.
|
||||
*
|
||||
* Copyright (C) 2012 Bert Vermeulen <bert@biot.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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include "config.h"
|
||||
#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
#include <math.h>
|
||||
|
||||
struct context {
|
||||
int num_enabled_probes;
|
||||
GPtrArray *probelist;
|
||||
GString *out;
|
||||
};
|
||||
|
||||
|
||||
static int init(struct sr_output *o)
|
||||
{
|
||||
struct context *ctx;
|
||||
struct sr_probe *probe;
|
||||
GSList *l;
|
||||
|
||||
sr_spew("output/analog: initializing");
|
||||
if (!o || !o->sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
if (!(ctx = g_try_malloc0(sizeof(struct context))))
|
||||
return SR_ERR_MALLOC;
|
||||
o->internal = ctx;
|
||||
|
||||
/* Get the number of probes and their names. */
|
||||
ctx->probelist = g_ptr_array_new();
|
||||
for (l = o->sdi->probes; l; l = l->next) {
|
||||
probe = l->data;
|
||||
if (!probe || !probe->enabled)
|
||||
continue;
|
||||
g_ptr_array_add(ctx->probelist, probe->name);
|
||||
ctx->num_enabled_probes++;
|
||||
}
|
||||
|
||||
ctx->out = g_string_sized_new(512);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static void si_printf(float value, GString *out, char *unitstr)
|
||||
{
|
||||
|
||||
if (value > 1000000000L)
|
||||
g_string_append_printf(out, "%f G%s", value / 1000000000L, unitstr);
|
||||
else if (value > 1000000)
|
||||
g_string_append_printf(out, "%f M%s", value / 1000000, unitstr);
|
||||
else if (value > 1000)
|
||||
g_string_append_printf(out, "%f k%s", value / 1000, unitstr);
|
||||
else if (value < 0.000000000001)
|
||||
g_string_append_printf(out, "%f p%s", value * 1000000000000, unitstr);
|
||||
else if (value < 0.000000001)
|
||||
g_string_append_printf(out, "%f n%s", value * 1000000000, unitstr);
|
||||
else if (value < 0.000001)
|
||||
g_string_append_printf(out, "%f u%s", value * 1000000, unitstr);
|
||||
else if (value < 0.001)
|
||||
g_string_append_printf(out, "%f m%s", value * 1000, unitstr);
|
||||
else
|
||||
g_string_append_printf(out, "%f %s", value, unitstr);
|
||||
|
||||
}
|
||||
|
||||
static void fancyprint(int unit, int mqflags, float value, GString *out)
|
||||
{
|
||||
|
||||
switch (unit) {
|
||||
case SR_UNIT_VOLT:
|
||||
si_printf(value, out, "V");
|
||||
break;
|
||||
case SR_UNIT_AMPERE:
|
||||
si_printf(value, out, "A");
|
||||
break;
|
||||
case SR_UNIT_OHM:
|
||||
si_printf(value, out, "");
|
||||
g_string_append_unichar(out, 0x2126);
|
||||
break;
|
||||
case SR_UNIT_FARAD:
|
||||
si_printf(value, out, "F");
|
||||
break;
|
||||
case SR_UNIT_KELVIN:
|
||||
si_printf(value, out, "K");
|
||||
break;
|
||||
case SR_UNIT_CELSIUS:
|
||||
si_printf(value, out, "");
|
||||
g_string_append_unichar(out, 0x00b0);
|
||||
g_string_append_c(out, 'C');
|
||||
break;
|
||||
case SR_UNIT_FAHRENHEIT:
|
||||
si_printf(value, out, "");
|
||||
g_string_append_unichar(out, 0x00b0);
|
||||
g_string_append_c(out, 'F');
|
||||
break;
|
||||
case SR_UNIT_HERTZ:
|
||||
si_printf(value, out, "Hz");
|
||||
break;
|
||||
case SR_UNIT_PERCENTAGE:
|
||||
g_string_append_printf(out, "%f%%", value);
|
||||
break;
|
||||
case SR_UNIT_BOOLEAN:
|
||||
if (value > 0)
|
||||
g_string_append_printf(out, "TRUE");
|
||||
else
|
||||
g_string_append_printf(out, "FALSE");
|
||||
break;
|
||||
}
|
||||
if (mqflags & SR_MQFLAG_AC)
|
||||
g_string_append_printf(out, " AC");
|
||||
else if (mqflags & SR_MQFLAG_DC)
|
||||
g_string_append_printf(out, " DC");
|
||||
g_string_append_c(out, '\n');
|
||||
|
||||
}
|
||||
|
||||
static GString *recv(struct sr_output *o, const struct sr_dev_inst *sdi,
|
||||
struct sr_datafeed_packet *packet)
|
||||
{
|
||||
struct sr_datafeed_analog *analog;
|
||||
struct context *ctx;
|
||||
float *fdata;
|
||||
int i, j;
|
||||
|
||||
if (!o || !o->sdi)
|
||||
return NULL;
|
||||
ctx = o->internal;
|
||||
|
||||
g_string_set_size(ctx->out, 0);
|
||||
switch (packet->type) {
|
||||
case SR_DF_HEADER:
|
||||
break;
|
||||
case SR_DF_FRAME_BEGIN:
|
||||
g_string_append_printf(ctx->out, "FRAME-BEGIN\n");
|
||||
break;
|
||||
case SR_DF_FRAME_END:
|
||||
g_string_append_printf(ctx->out, "FRAME-END\n");
|
||||
break;
|
||||
case SR_DF_ANALOG:
|
||||
analog = packet->payload;
|
||||
fdata = (float *)analog->data;
|
||||
for (i = 0; i < analog->num_samples; i++) {
|
||||
for (j = 0; j < ctx->num_enabled_probes; j++) {
|
||||
g_string_append_printf(ctx->out, "%s: ",
|
||||
(char *)g_ptr_array_index(ctx->probelist, j));
|
||||
fancyprint(analog->unit, analog->mqflags,
|
||||
fdata[i + j], ctx->out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ctx->out;
|
||||
}
|
||||
|
||||
static int cleanup(struct sr_output *o)
|
||||
{
|
||||
struct context *ctx;
|
||||
|
||||
if (!o || !o->sdi)
|
||||
return SR_ERR_ARG;
|
||||
ctx = o->internal;
|
||||
|
||||
g_ptr_array_free(ctx->probelist, 1);
|
||||
g_string_free(ctx->out, 1);
|
||||
g_free(ctx);
|
||||
o->internal = NULL;
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
|
||||
SR_PRIV struct sr_output_format output_analog = {
|
||||
.id = "analog",
|
||||
.description = "Analog data",
|
||||
.df_type = SR_DF_ANALOG,
|
||||
.init = init,
|
||||
.recv = recv,
|
||||
.cleanup = cleanup
|
||||
};
|
|
@ -30,6 +30,7 @@ extern SR_PRIV struct sr_output_format output_gnuplot;
|
|||
extern SR_PRIV struct sr_output_format output_chronovu_la8;
|
||||
extern SR_PRIV struct sr_output_format output_csv;
|
||||
extern SR_PRIV struct sr_output_format output_float;
|
||||
extern SR_PRIV struct sr_output_format output_analog;
|
||||
/* extern SR_PRIV struct sr_output_format output_analog_gnuplot; */
|
||||
|
||||
static struct sr_output_format *output_module_list[] = {
|
||||
|
@ -43,6 +44,7 @@ static struct sr_output_format *output_module_list[] = {
|
|||
&output_chronovu_la8,
|
||||
&output_csv,
|
||||
&output_float,
|
||||
&output_analog,
|
||||
/* &output_analog_gnuplot, */
|
||||
NULL,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue