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
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

