From: Bert Vermeulen Date: Sat, 19 Apr 2014 10:31:50 +0000 (+0200) Subject: output/hex: Rewrite for new output API. X-Git-Tag: libsigrok-0.3.0~77 X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=8d3af2e868c4fcfb0119ec74c541fb5d04a10fce output/hex: Rewrite for new output API. --- diff --git a/Makefile.am b/Makefile.am index 149f7177..1cc6b35f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,7 +61,7 @@ libsigrok_la_SOURCES += \ output/output.c \ output/text/text.c \ output/text/text.h \ - output/text/hex.c \ + output/hex.c \ output/text/ascii.c # Hardware (common files) diff --git a/output/hex.c b/output/hex.c new file mode 100644 index 00000000..85ce9069 --- /dev/null +++ b/output/hex.c @@ -0,0 +1,226 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2014 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 "libsigrok.h" +#include "libsigrok-internal.h" + +#define LOG_PREFIX "output/hex" + +#define DEFAULT_SAMPLES_PER_LINE 192 + +struct context { + unsigned int num_enabled_channels; + int samples_per_line; + int bit_cnt; + int spl_cnt; + int trigger; + int *channel_index; + char **channel_names; + char **line_values; + uint8_t *sample_buf; + GString **lines; + GString *header; +}; + +static int init(struct sr_output *o) +{ + struct context *ctx; + struct sr_channel *ch; + GSList *l; + GVariant *gvar; + uint64_t samplerate; + unsigned int i, j; + int spl, num_channels; + char *samplerate_s; + + if (!o || !o->sdi) + return SR_ERR_ARG; + ctx = g_malloc0(sizeof(struct context)); + o->internal = ctx; + ctx->trigger = -1; + + if (o->param && o->param[0]) { + if ((spl = strtoul(o->param, NULL, 10)) < 1) + return SR_ERR_ARG; + } else + spl = DEFAULT_SAMPLES_PER_LINE; + ctx->samples_per_line = spl; + + for (l = o->sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type != SR_CHANNEL_LOGIC) + continue; + if (!ch->enabled) + continue; + ctx->num_enabled_channels++; + } + ctx->channel_index = g_malloc(sizeof(int) * ctx->num_enabled_channels); + ctx->channel_names = g_malloc(sizeof(char *) * ctx->num_enabled_channels); + ctx->lines = g_malloc(sizeof(GString *) * ctx->num_enabled_channels); + ctx->sample_buf = g_malloc(ctx->num_enabled_channels); + + j = 0; + for (i = 0, l = o->sdi->channels; l; l = l->next, i++) { + ch = l->data; + if (ch->type != SR_CHANNEL_LOGIC) + continue; + if (!ch->enabled) + continue; + ctx->channel_index[j] = ch->index; + ctx->channel_names[j] = ch->name; + ctx->lines[j] = g_string_sized_new(80); + ctx->sample_buf[j] = 0; + g_string_printf(ctx->lines[j], "%s:", ch->name); + j++; + } + + ctx->header = g_string_sized_new(512); + g_string_printf(ctx->header, "%s\n", PACKAGE_STRING); + num_channels = g_slist_length(o->sdi->channels); + if (sr_config_get(o->sdi->driver, o->sdi, NULL, SR_CONF_SAMPLERATE, + &gvar) == SR_OK) { + samplerate = g_variant_get_uint64(gvar); + samplerate_s = sr_samplerate_string(samplerate); + g_string_append_printf(ctx->header, "Acquisition with %d/%d channels at %s\n", + ctx->num_enabled_channels, num_channels, samplerate_s); + g_free(samplerate_s); + g_variant_unref(gvar); + } + + return SR_OK; +} + +static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, + const struct sr_datafeed_packet *packet, GString **out) +{ + const struct sr_datafeed_logic *logic; + struct context *ctx; + int idx, pos, offset; + uint64_t i, j; + gchar *p; + + (void)sdi; + + *out = NULL; + if (!o || !o->sdi) + return SR_ERR_ARG; + if (!(ctx = o->internal)) + return SR_ERR_ARG; + + switch (packet->type) { + case SR_DF_TRIGGER: + ctx->trigger = ctx->spl_cnt; + break; + case SR_DF_LOGIC: + if (ctx->header) { + /* The header is still here, this must be the first packet. */ + *out = ctx->header; + ctx->header = NULL; + } else + *out = g_string_sized_new(512); + + logic = packet->payload; + for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) { + ctx->spl_cnt++; + pos = ctx->spl_cnt & 7; + for (j = 0; j < ctx->num_enabled_channels; j++) { + idx = ctx->channel_index[j]; + p = logic->data + i + idx / 8; + ctx->sample_buf[j] <<= 1; + if (*p & (1 << (idx % 8))) + ctx->sample_buf[j] |= 1; + if (ctx->spl_cnt && pos == 0) { + /* Buffered a byte's worth, output hex. */ + g_string_append_printf(ctx->lines[j], "%.2x ", + ctx->sample_buf[j]); + ctx->sample_buf[j] = 0; + } + + if (ctx->spl_cnt == ctx->samples_per_line) { + /* Flush line buffers. */ + g_string_append_len(*out, ctx->lines[j]->str, ctx->lines[j]->len); + g_string_append_c(*out, '\n'); + if (j == ctx->num_enabled_channels - 1 && ctx->trigger > -1) { + offset = ctx->trigger + ctx->trigger / 8; + g_string_append_printf(*out, "T:%*s^ %d\n", offset, "", ctx->trigger); + ctx->trigger = -1; + } + g_string_printf(ctx->lines[j], "%s:", ctx->channel_names[j]); + } + } + if (ctx->spl_cnt == ctx->samples_per_line) + /* Line buffers were already flushed. */ + ctx->spl_cnt = 0; + } + break; + case SR_DF_END: + if (ctx->spl_cnt) { + /* Line buffers need flushing. */ + *out = g_string_sized_new(512); + for (i = 0; i < ctx->num_enabled_channels; i++) { + if (ctx->spl_cnt & 7) + g_string_append_printf(ctx->lines[i], "%.2x ", + ctx->sample_buf[i] << (8 - (ctx->spl_cnt & 7))); + g_string_append_len(*out, ctx->lines[i]->str, ctx->lines[i]->len); + g_string_append_c(*out, '\n'); + } + } + break; + } + + return SR_OK; +} + +static int cleanup(struct sr_output *o) +{ + struct context *ctx; + unsigned int i; + + if (!o) + return SR_ERR_ARG; + + if (!(ctx = o->internal)) + return SR_OK; + + g_free(ctx->header); + g_free(ctx->channel_index); + g_free(ctx->sample_buf); + g_free(ctx->channel_names); + for (i = 0; i < ctx->num_enabled_channels; i++) + g_string_free(ctx->lines[i], TRUE); + g_free(ctx->lines); + if (ctx->header) + g_string_free(ctx->header, TRUE); + g_free(ctx); + o->internal = NULL; + + return SR_OK; +} + +SR_PRIV struct sr_output_format output_hex = { + .id = "hex", + .description = "Hexadecimal", + .init = init, + .receive = receive, + .cleanup = cleanup, +}; + diff --git a/output/output.c b/output/output.c index 80552f6d..76ff758b 100644 --- a/output/output.c +++ b/output/output.c @@ -50,7 +50,7 @@ /** @cond PRIVATE */ extern SR_PRIV struct sr_output_format output_bits; -extern SR_PRIV struct sr_output_format output_text_hex; +extern SR_PRIV struct sr_output_format output_hex; extern SR_PRIV struct sr_output_format output_text_ascii; extern SR_PRIV struct sr_output_format output_binary; extern SR_PRIV struct sr_output_format output_vcd; @@ -64,7 +64,7 @@ extern SR_PRIV struct sr_output_format output_analog; static struct sr_output_format *output_module_list[] = { &output_bits, - &output_text_hex, + &output_hex, &output_text_ascii, &output_binary, &output_vcd, diff --git a/output/text/hex.c b/output/text/hex.c deleted file mode 100644 index 14fc6d1a..00000000 --- a/output/text/hex.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010-2012 Bert Vermeulen - * Copyright (C) 2011 HÃ¥vard Espeland - * - * 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 "libsigrok.h" -#include "libsigrok-internal.h" -#include "text.h" - -#define LOG_PREFIX "output/hex" - -SR_PRIV int init_hex(struct sr_output *o) -{ - return init(o, DEFAULT_BPL_HEX, MODE_HEX); -} - -SR_PRIV int data_hex(struct sr_output *o, const uint8_t *data_in, - uint64_t length_in, uint8_t **data_out, - uint64_t *length_out) -{ - struct context *ctx; - unsigned int outsize, offset, p; - int max_linelen; - const uint8_t *sample; - uint8_t *outbuf; - - ctx = o->internal; - max_linelen = SR_MAX_CHANNELNAME_LEN + 3 + ctx->samples_per_line - + ctx->samples_per_line / 2; - outsize = length_in / ctx->unitsize * ctx->num_enabled_channels - / ctx->samples_per_line * max_linelen + 512; - - if (!(outbuf = g_try_malloc0(outsize + 1))) { - sr_err("%s: outbuf malloc failed", __func__); - return SR_ERR_MALLOC; - } - - outbuf[0] = '\0'; - if (ctx->header) { - /* The header is still here, this must be the first packet. */ - strncpy((char *)outbuf, ctx->header, outsize); - g_free(ctx->header); - ctx->header = NULL; - } - - ctx->line_offset = 0; - for (offset = 0; offset <= length_in - ctx->unitsize; - offset += ctx->unitsize) { - sample = data_in + offset; - for (p = 0; p < ctx->num_enabled_channels; p++) { - ctx->linevalues[p] <<= 1; - if (sample[p / 8] & ((uint8_t) 1 << (p % 8))) - ctx->linevalues[p] |= 1; - sprintf((char *)ctx->linebuf + (p * ctx->linebuf_len) + - ctx->line_offset, "%.2x", ctx->linevalues[p]); - } - ctx->spl_cnt++; - - /* Add a space after every complete hex byte. */ - if ((ctx->spl_cnt & 7) == 0) { - for (p = 0; p < ctx->num_enabled_channels; p++) - ctx->linebuf[p * ctx->linebuf_len + - ctx->line_offset + 2] = ' '; - ctx->line_offset += 3; - } - - /* End of line. */ - if (ctx->spl_cnt >= ctx->samples_per_line) { - flush_linebufs(ctx, outbuf); - ctx->line_offset = ctx->spl_cnt = 0; - } - } - - *data_out = outbuf; - *length_out = strlen((const char *)outbuf); - - return SR_OK; -} - -SR_PRIV struct sr_output_format output_text_hex = { - .id = "hex", - .description = "Hexadecimal", - .df_type = SR_DF_LOGIC, - .init = init_hex, - .data = data_hex, - .event = event, - .cleanup = text_cleanup, -};