From 161a8a272699a7b818ddab01043838f07d7cf6eb Mon Sep 17 00:00:00 2001 From: Bert Vermeulen Date: Sat, 8 Sep 2012 13:24:48 +0200 Subject: [PATCH] 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. --- output/Makefile.am | 1 + output/analog.c | 200 +++++++++++++++++++++++++++++++++++++++++++++ output/output.c | 2 + 3 files changed, 203 insertions(+) create mode 100644 output/analog.c diff --git a/output/Makefile.am b/output/Makefile.am index 166fe3ca..44b4bd4d 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -30,6 +30,7 @@ libsigrokoutput_la_SOURCES = \ chronovu_la8.c \ csv.c \ float.c \ + analog.c \ output.c libsigrokoutput_la_CFLAGS = \ diff --git a/output/analog.c b/output/analog.c new file mode 100644 index 00000000..4ae8550f --- /dev/null +++ b/output/analog.c @@ -0,0 +1,200 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2012 Bert Vermeulen + * + * 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 . + */ + +#include +#include +#include +#include "config.h" +#include "libsigrok.h" +#include "libsigrok-internal.h" +#include + +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 +}; diff --git a/output/output.c b/output/output.c index 471ee9c7..cb5826b2 100644 --- a/output/output.c +++ b/output/output.c @@ -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, };