]> sigrok.org Git - libsigrok.git/commitdiff
sr: add new analog output module
authorBert Vermeulen <redacted>
Sat, 8 Sep 2012 11:24:48 +0000 (13:24 +0200)
committerBert Vermeulen <redacted>
Sat, 8 Sep 2012 11:24:48 +0000 (13:24 +0200)
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
output/analog.c [new file with mode: 0644]
output/output.c

index 166fe3ca9edadfe820a09ab782806e0fd60b7472..44b4bd4d9a5ee81f50b33688d6e69c70b1c68f8d 100644 (file)
@@ -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 (file)
index 0000000..4ae8550
--- /dev/null
@@ -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
+};
index 471ee9c79f7997263eaebdba952718484977aa5c..cb5826b2efa74f409c006bb3a804fdf4bd3cc933 100644 (file)
@@ -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,
 };