Le Thu, 24 Jul 2014 19:23:53 +0200,
Bert Vermeulen <[email protected]> a écrit :

> On 07/24/2014 12:01 PM, Matthieu CASTET wrote:
> > Hi,
> > 
> > I have something that is working for logic signal, but the analog part
> > is weird.
> 
> Excellent! Do you have some code we can look at, on github or some place?
> 
I attached the current version of the code. Code need cleaning.

I also attach a sample of an i2c analog trace.



> > In pulseview I saw nothing, but with sigrok-cli and analog output I see
> > the data.
> > 
> > Using pulseview with wav file show the same behavior (no signal).
> > 
> > Is there something special to do to see analog signal in pulseview ?
> 
> Looks like that's a bug. I've filed this:
>       http://sigrok.org/bugzilla/show_bug.cgi?id=387
> 
> 
Ok, for logic signal the samplerate looks also weird in pulseview.


Matthieu

Attachment: scope_10.bin
Description: Binary data

commit 403620f691fdc404d8ff8d2540832e4b11cd7e95
Author: Matthieu CASTET <[email protected]>
Date:   Fri Jul 25 18:12:02 2014 +0200

    add agilent_bin

diff --git a/Makefile.am b/Makefile.am
index 8a8a2e1..b564dde 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,6 +46,7 @@ libsigrok_la_SOURCES += \
 	input/binary.c \
 	input/chronovu_la8.c \
 	input/csv.c \
+	input/agilent_bin.c \
 	input/input.c \
 	input/vcd.c \
 	input/wav.c
diff --git a/input/agilent_bin.c b/input/agilent_bin.c
new file mode 100644
index 0000000..4978aa1
--- /dev/null
+++ b/input/agilent_bin.c
@@ -0,0 +1,441 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2014 Matthieu CASTET <[email protected]>
+ *
+ * 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/>.
+ */
+
+/* documentation for parsing the Agilent binary format can be found on
+http://cp.literature.agilent.com/litweb/pdf/54695-97015.pdf
+http://www.home.agilent.com/upload/cmc_upload/All/binToAscii.c?&cc=FR&lc=fre
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+#define LOG_PREFIX "input/agilbin"
+
+#define MAX_CHAN 20
+
+#define DATE_TIME_STRING_LENGTH 16
+#define FRAME_STRING_LENGTH 24
+#define SIGNAL_STRING_LENGTH 16
+
+/*
+ * The CSV input module has the following options:
+ *
+ * analog2logic: convert analog signal to logic signal
+ */
+
+struct WaveformHeader {
+   int32_t HeaderSize;
+   int32_t WaveformType;
+   int32_t NWaveformBuffers;
+   int32_t Points;
+   int32_t Count;
+   uint32_t /*float*/ XDisplayRange;
+   uint64_t /*double*/ XDisplayOrigin;
+   uint64_t /*double*/ XIncrement;
+   uint64_t /*double*/ XOrigin;
+   int32_t XUnits;
+   int32_t YUnits;
+   uint8_t Date[DATE_TIME_STRING_LENGTH];
+   uint8_t Time[DATE_TIME_STRING_LENGTH];
+   uint8_t Frame[FRAME_STRING_LENGTH];
+   uint8_t WaveformLabel[SIGNAL_STRING_LENGTH];
+   uint32_t /*double*/ TimeTag;
+   uint32_t SegmentIndex;
+};
+
+struct WaveformDataHeader {
+	int32_t HeaderSize;
+	int16_t BufferType;
+	int16_t BytesPerPoint;
+	int32_t BufferSize;
+	uint8_t data[0];
+};
+
+enum {
+	TYPE_ANALOG,
+	TYPE_DIGITAL,
+};
+
+struct context {
+	/* Current selected period. */
+	double period;
+
+	/* Number of channels. */
+	gsize num_channels;
+
+	int num_sample;
+
+	/* digital */
+	/* Size of the sample buffer. */
+	gsize sample_buffer_size;
+	/* Buffer to store sample data. */
+	uint8_t *sample_buffer;
+
+	/* analog */
+	struct sr_datafeed_analog analog[MAX_CHAN];
+
+	GMappedFile *mapped_file;
+
+	struct WaveformDataHeader *buffer_header[MAX_CHAN];
+
+	int analog2logic;
+};
+
+static int format_match(const char *filename)
+{
+	int fd, l;
+	char buf[12];
+	struct stat st;
+	if (!filename) {
+		sr_err("%s: filename was NULL.", __func__);
+		return FALSE;
+	}
+
+	if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
+		sr_err("Input file '%s' does not exist.", filename);
+		return FALSE;
+	}
+
+	if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
+		sr_err("Input file '%s' not a regular file.", filename);
+		return FALSE;
+	}
+
+	if (stat(filename, &st) == -1)
+		return FALSE;
+	if (st.st_size < 12)
+		/* Minimum size of header */
+		return FALSE;
+
+	if ((fd = open(filename, O_RDONLY)) == -1)
+		return FALSE;
+
+	l = read(fd, buf, sizeof(buf));
+	close(fd);
+	if (l != sizeof(buf))
+		return FALSE;
+
+	if (buf[0] != 'A' || buf[1] != 'G')
+		return FALSE;
+
+	if (GUINT32_FROM_LE(*(uint32_t *)(buf + 4)) != (uint32_t)st.st_size)
+		return FALSE;
+
+	return TRUE;
+}
+
+static void free_context(struct context *ctx)
+{
+	gsize j;
+	if (!ctx)
+		return;
+
+	for (j = 0; j < ctx->num_channels; j++) {
+		if (ctx->analog[j].channels)
+			g_slist_free(ctx->analog[j].channels);
+	}
+	if (ctx->sample_buffer)
+		g_free(ctx->sample_buffer);
+
+	if (ctx->mapped_file)
+		g_mapped_file_unref(ctx->mapped_file);
+
+	g_free(ctx);
+}
+
+static int send_samples(const struct sr_dev_inst *sdi, uint8_t *buffer,
+			gsize buffer_size)
+{
+	int res;
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_logic logic;
+
+	if (!buffer_size)
+		return SR_OK;
+
+	packet.type = SR_DF_LOGIC;
+	packet.payload = &logic;
+	logic.unitsize = buffer_size;
+	logic.length = buffer_size;
+	logic.data = buffer;
+
+	res = sr_session_send(sdi, &packet);
+
+	return res;
+}
+
+static int send_samples_ana(const struct sr_dev_inst *sdi, float *fdata,
+		struct sr_datafeed_analog *analog)
+{
+	int res;
+	struct sr_datafeed_packet packet;
+
+	packet.type = SR_DF_ANALOG;
+	packet.payload = analog;
+	analog->data = fdata;
+
+	res = sr_session_send(sdi, &packet);
+
+	return res;
+}
+
+static int init(struct sr_input *in, const char *filename)
+{
+	struct context *ctx;
+	gsize i;
+	gchar *data;
+
+	if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
+		sr_err("Context malloc failed.");
+		return SR_ERR_MALLOC;
+	}
+	
+	memset(ctx, 0, sizeof(*ctx));
+
+	/* Create a virtual device. */
+	in->sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, NULL, NULL, NULL);
+	in->internal = ctx;
+
+	/* Set default period. */
+	ctx->period = 0;
+
+	/*
+	 * Enable auto-detection of the number of channels in multi column mode
+	 * and enforce the specification of the number of channels in single
+	 * column mode.
+	 */
+	ctx->num_channels = 0;
+	ctx->num_sample = 0;
+
+	if (in->param) {
+		const char *param;
+		if ((param = g_hash_table_lookup(in->param, "analog2logic")))
+			ctx->analog2logic = g_ascii_strtoull(param, NULL, 10);
+	}
+
+	ctx->mapped_file = g_mapped_file_new(filename, FALSE, NULL);
+	if (!ctx->mapped_file) {
+		sr_err("Input file '%s' could not be opened.", filename);
+		goto error;
+	}
+
+	data = g_mapped_file_get_contents(ctx->mapped_file);
+
+	ctx->num_channels = GUINT32_FROM_LE(*(uint32_t *)(data + 8));
+	if (ctx->num_channels > MAX_CHAN) {
+		sr_err("unsupported number of channels %d\n", ctx->num_channels);
+		goto error;
+	}
+	/* goto waveform header */
+	data += 12;
+	for (i = 0; i < ctx->num_channels; i++) {
+		struct WaveformHeader *whdr = (struct WaveformHeader *)data;
+		struct WaveformDataHeader *wdhdr;
+		struct sr_channel *ch;
+		double period;
+
+		data += whdr->HeaderSize;
+		wdhdr = (struct WaveformDataHeader *)data;
+		/* skip header */
+		data += wdhdr->HeaderSize;
+		/* skip data */
+		data += wdhdr->BufferSize;
+
+		sr_dbg("ch name %s\n", whdr->WaveformLabel);
+		/* XXX portable way to read float ? */
+		memcpy(&period, &whdr->XIncrement, sizeof(whdr->XIncrement));
+
+		if (!ctx->period) {
+			ctx->period = period;
+		}
+		else if (ctx->period != period) {
+			sr_err("channel with different period is not supported (%f %f)\n",
+					period, ctx->period);
+			goto error;
+		}
+
+		if (!ctx->num_sample)
+			ctx->num_sample = whdr->Points;
+		else if (ctx->num_sample != whdr->Points) {
+			sr_err("channel with different number of sample is not supported\n");
+			goto error;
+		}
+		if (whdr->NWaveformBuffers != 1) {
+			sr_err("multiple segments is not supported\n");
+			goto error;
+		}
+
+		if (wdhdr->BufferType == 6) {
+			if (wdhdr->BytesPerPoint != 1) {
+				sr_err("bad data format for logic channel\n");
+				goto error;
+			}
+		}
+		else {
+			if (wdhdr->BytesPerPoint != 4) {
+				sr_err("bad data format for analog channel\n");
+				goto error;
+			}
+		}
+
+		if (wdhdr->BufferType == 6 || ctx->analog2logic) {
+			ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE,
+					(const char *)whdr->WaveformLabel);
+		}
+		else {
+			ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE,
+					(const char *)whdr->WaveformLabel);
+			if (ch)
+				ctx->analog[i].channels = g_slist_append(NULL, ch);
+			ctx->analog[i].num_samples = 1;
+			switch (whdr->YUnits) {
+				case 1:
+					ctx->analog[i].mq = SR_MQ_VOLTAGE;
+					ctx->analog[i].unit = SR_UNIT_VOLT;
+					break;
+				default:
+					ctx->analog[i].mq = 0;
+					ctx->analog[i].unit = 0;
+			};
+		}
+
+		if (!ch) {
+			sr_err("Channel creation failed.");
+			goto error;
+		}
+
+		in->sdi->channels = g_slist_append(in->sdi->channels, ch);
+
+		sr_dbg("%d sample every %fs\n", whdr->Points, ctx->period);
+		/* skip header */
+		ctx->buffer_header[i] = wdhdr;
+		sr_dbg("type %d (%d per pt)\n", wdhdr->BufferType, wdhdr->BytesPerPoint);
+	}
+
+
+	ctx->sample_buffer_size = (ctx->num_channels + 7) >> 3;
+
+	if (!(ctx->sample_buffer = g_try_malloc(ctx->sample_buffer_size))) {
+		sr_err("Sample buffer malloc failed.");
+		free_context(ctx);
+		return SR_ERR_MALLOC;
+	}
+
+	return SR_OK;
+error:
+	free_context(ctx);
+	return SR_ERR;
+}
+
+static inline int digitalize(float val)
+{
+	/* use 0.9 to be compatible with 1.8 and 3.3 signal */
+	if (val > 0.9)
+		return 1;
+	else
+		return 0;
+}
+
+static int loadfile(struct sr_input *in, const char *filename)
+{
+	int res;
+	struct context *ctx;
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_meta meta;
+	int j;
+
+	(void)filename;
+
+	ctx = in->internal;
+
+	/* Send header packet to the session bus. */
+	std_session_send_df_header(in->sdi, LOG_PREFIX);
+
+	if (ctx->period) {
+		struct sr_config *cfg;
+		packet.type = SR_DF_META;
+		packet.payload = &meta;
+		cfg = sr_config_new(SR_CONF_SAMPLERATE,
+			g_variant_new_uint64(1.0/ctx->period));
+		meta.config = g_slist_append(NULL, cfg);
+		sr_session_send(in->sdi, &packet);
+		sr_config_free(cfg);
+	}
+
+	for (j = 0; j < ctx->num_sample; j++) {
+		gsize i;
+
+		/* Clear buffer in order to set bits only. */
+		memset(ctx->sample_buffer, 0, (ctx->num_channels + 7) >> 3);
+
+		for (i = 0; i < ctx->num_channels; i++) {
+			if (ctx->buffer_header[i]->BufferType == 6) {
+				int data;
+				data = ctx->buffer_header[i]->data[j];
+				if (data) {
+					ctx->sample_buffer[i / 8] |= (1 << (i % 8));
+				}
+			}
+			else {
+				float fdata;
+				memcpy(&fdata, &ctx->buffer_header[i]->data[j*4], 4);
+				if (ctx->analog2logic) {
+					int data;
+					data = digitalize(fdata);
+					if (data) {
+						ctx->sample_buffer[i / 8] |= (1 << (i % 8));
+					}
+				}
+				else
+					send_samples_ana(in->sdi, &fdata, &ctx->analog[i]);
+			}
+		}
+		/* Send sample data to the session bus. */
+		res = send_samples(in->sdi, ctx->sample_buffer,
+			ctx->sample_buffer_size);
+
+		if (res != SR_OK) {
+			sr_err("Sending samples failed.");
+			free_context(ctx);
+			return SR_ERR;
+		}
+	}
+
+	/* Send end packet to the session bus. */
+	packet.type = SR_DF_END;
+	sr_session_send(in->sdi, &packet);
+
+	free_context(ctx);
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_input_format input_agilbin = {
+	.id = "agilbin",
+	.description = "Agilent Binary format",
+	.format_match = format_match,
+	.init = init,
+	.loadfile = loadfile,
+};
diff --git a/input/input.c b/input/input.c
index d22b373..bc46bd6 100644
--- a/input/input.c
+++ b/input/input.c
@@ -55,11 +55,13 @@ extern SR_PRIV struct sr_input_format input_csv;
 extern SR_PRIV struct sr_input_format input_binary;
 extern SR_PRIV struct sr_input_format input_vcd;
 extern SR_PRIV struct sr_input_format input_wav;
+extern SR_PRIV struct sr_input_format input_agilbin;
 /* @endcond */
 
 static struct sr_input_format *input_module_list[] = {
 	&input_vcd,
 	&input_chronovu_la8,
+	&input_agilbin,
 	&input_wav,
 	&input_csv,
 	/* This one has to be last, because it will take any input. */
------------------------------------------------------------------------------
Want fast and easy access to all the code in your enterprise? Index and
search up to 200,000 lines of code with a free copy of Black Duck
Code Sight - the same software that powers the world's largest code
search on Ohloh, the Black Duck Open Hub! Try it now.
http://p.sf.net/sfu/bds
_______________________________________________
sigrok-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to