From: Uwe Hermann Date: Tue, 6 Apr 2010 12:38:47 +0000 (+0200) Subject: Gnuplot output format support. X-Git-Tag: libsigrok-0.1.0~583 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=e2ad47b5b0ad98fc99579d4cd9ebee7db2a03d82;p=libsigrok.git Gnuplot output format support. --- diff --git a/Makefile.am b/Makefile.am index 75dd31b9..e0d0a4af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,6 +40,7 @@ libsigrok_la_SOURCES = \ hardware/zeroplus-logic-cube/zeroplus.c \ output/output_text.c \ output/output_vcd.c \ + output/output_gnuplot.c \ output/output.c libsigrok_la_LIBADD = $(LIBOBJS) diff --git a/output/output.c b/output/output.c index 63da6352..9bda9893 100644 --- a/output/output.c +++ b/output/output.c @@ -22,21 +22,17 @@ extern struct output_format output_text_binary; extern struct output_format output_text_hex; extern struct output_format output_vcd; - +extern struct output_format output_gnuplot; struct output_format *output_module_list[] = { &output_text_binary, &output_text_hex, &output_vcd, + &output_gnuplot, NULL, }; - - struct output_format **output_list(void) { - return output_module_list; } - - diff --git a/output/output_gnuplot.c b/output/output_gnuplot.c new file mode 100644 index 00000000..25306d8d --- /dev/null +++ b/output/output_gnuplot.c @@ -0,0 +1,189 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2010 Uwe Hermann + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include "config.h" + +struct context { + int num_enabled_probes; + int unitsize; + char *probelist[65]; + char *header; +}; + +const char *gnuplot_header = "\ +# Sample data in space-separated columns format usable by gnuplot\n\ +#\n\ +# Generated by: %s on %s\n\ +# Comment: Acquisition with %d/%d probes at %s\n\ +# Timescale: %d %s\n\ +# Column assignment:\n%s\n"; + +static int init(struct output *o) +{ +/* Maximum header length */ +#define MAX_HEADER_LEN 2048 + + struct context *ctx; + struct probe *probe; + GSList *l; + uint64_t samplerate; + int i, b, num_probes; + char *c; + char sbuf[10], wbuf[1000]; + + ctx = malloc(sizeof(struct context)); + if (ctx == NULL) + return SIGROK_ERR_MALLOC; + o->internal = ctx; + ctx->num_enabled_probes = 0; + for (l = o->device->probes; l; l = l->next) { + probe = l->data; + if (probe->enabled) + ctx->probelist[ctx->num_enabled_probes++] = probe->name; + } + + ctx->probelist[ctx->num_enabled_probes] = 0; + ctx->unitsize = (ctx->num_enabled_probes + 7) / 8; + + /* TODO: Allow for configuration via o->param. */ + + ctx->header = calloc(1, MAX_HEADER_LEN + 1); + if (ctx->header == NULL) + return SIGROK_ERR_MALLOC; + num_probes = g_slist_length(o->device->probes); + /* TODO: Handle num_probes == 0, too many probes, etc. */ + samplerate = *((uint64_t *) o->device->plugin->get_device_info( + o->device->plugin_index, DI_CUR_SAMPLERATE)); + + /* Samplerate string */ + if (samplerate >= GHZ(1)) + snprintf(sbuf, 10, "%"PRIu64" GHz", samplerate / 1000000000); + else if (samplerate >= MHZ(1)) + snprintf(sbuf, 10, "%"PRIu64" MHz", samplerate / 1000000); + else if (samplerate >= KHZ(1)) + snprintf(sbuf, 10, "%"PRIu64" KHz", samplerate / 1000); + else + snprintf(sbuf, 10, "%"PRIu64" Hz", samplerate); + + /* Columns / channels */ + wbuf[0] = '\0'; + for (i = 0; i < ctx->num_enabled_probes; i++) { + c = (char *)&wbuf + strlen((char *)&wbuf); + sprintf(c, "# Column %d: channel %s\n", i, ctx->probelist[i]); + } + + /* TODO: date: File or signals? Make y/n configurable. */ + /* TODO: Timescale */ + b = snprintf(ctx->header, MAX_HEADER_LEN, gnuplot_header, + PACKAGE_STRING, "TODO", ctx->num_enabled_probes, + num_probes, (char *)&sbuf, 1, "ns", (char *)&wbuf); + + /* TODO: Handle snprintf errors. */ + + return 0; +} + +static int event(struct output *o, int event_type, char **data_out, + uint64_t *length_out) +{ + struct context *ctx; + char *outbuf; + int outlen = 1; /* FIXME */ + + ctx = o->internal; + switch(event_type) { + case DF_TRIGGER: + break; + case DF_END: + outbuf = calloc(1, 1); // FIXME + if (outbuf == NULL) + return SIGROK_ERR_MALLOC; + *data_out = outbuf; + *length_out = outlen; + free(o->internal); + o->internal = NULL; + break; + } + + return SIGROK_OK; +} + +static int data(struct output *o, char *data_in, uint64_t length_in, + char **data_out, uint64_t *length_out) +{ + struct context *ctx; + int offset, outsize, p, curbit; + uint64_t sample, count = 0; + char *outbuf, *c; + + ctx = o->internal; + outsize = strlen(ctx->header); + outbuf = calloc(1, outsize + 1 + 10000); // FIXME: Use realloc(). + if (outbuf == NULL) + return SIGROK_ERR_MALLOC; + if (ctx->header) { + /* The header is still here, this must be the first packet. */ + strncpy(outbuf, ctx->header, outsize); + free(ctx->header); + ctx->header = NULL; + } else { + outbuf[0] = 0; + } + + /* TODO: Are disabled probes handled correctly? */ + + for (offset = 0; offset <= length_in - ctx->unitsize; + offset += ctx->unitsize) { + memcpy(&sample, data_in + offset, ctx->unitsize); + + /* The first column is a counter (needed for gnuplot). */ + c = outbuf + strlen(outbuf); + sprintf(c, "%"PRIu64"\t\t", count++); + + /* The next columns are the values of all channels. */ + for (p = 0; p < ctx->num_enabled_probes; p++) { + curbit = (sample & ((uint64_t) (1 << p))) != 0; + c = outbuf + strlen(outbuf); + sprintf(c, "%d ", curbit); + } + + c = outbuf + strlen(outbuf); + sprintf(c, "\n"); + + /* TODO: realloc() if strlen(outbuf) is almost "full"... */ + } + + *data_out = outbuf; + *length_out = strlen(outbuf); + + return SIGROK_OK; +} + +struct output_format output_gnuplot = { + "gnuplot", + "Gnuplot", + init, + data, + event, +};