X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Foutput%2Fwavedrom.c;h=65324bdc45f0a9c60d8c06456253ccdd756a9853;hb=f5c697bfe6d80c95051eaa1f52e1fefb54effa97;hp=67f33b60da8b6f1c10f9baf8abbdfd3315779a6e;hpb=dd5735c998264699d586a52b6ed5b4bf64397ee0;p=libsigrok.git diff --git a/src/output/wavedrom.c b/src/output/wavedrom.c index 67f33b60..65324bdc 100644 --- a/src/output/wavedrom.c +++ b/src/output/wavedrom.c @@ -69,6 +69,79 @@ static GString *wavedrom_render(const struct context *ctx) return output; } +static void process_logic(const struct context *ctx, + const struct sr_datafeed_logic *logic) +{ + size_t sample_count, ch, i; + uint8_t *sample, bit; + GString *accu; + + if (!ctx->channel_count) + return; + + /* + * Extract the logic bits for each channel and store them + * as wavedrom letters (1/0) in each channel's text string. + * This transforms the input which consists of sample sets + * that span multiple channels into output stripes per logic + * channel which consist of bits for that individual channel. + * + * TODO Reduce memory consumption during accumulation of + * output data. + * + * Ideally we'd accumulate binary chunks, and defer conversion + * to the text format. Analog data already won't get here, only + * logic data does. When the per-channel transformation also + * gets deferred until later, then the only overhead would be + * for disabled logic channels. Which may be acceptable or even + * negligable. + * + * An optional addition to the above mentioned accumulation of + * binary data is RLE compression. Mark both the position in the + * accumulated data as well as a repetition counter, instead of + * repeatedly storing the same sample set. The efficiency of + * this approach of course depends on the change rate of input + * data. But the approach perfectly matches the WaveDrom syntax + * for repeated bit patterns, and thus is easily handled in the + * text rendering stage of the output module. + */ + sample_count = logic->length / logic->unitsize; + for (i = 0; i < sample_count; i++) { + sample = logic->data + i * logic->unitsize; + for (ch = 0; ch < ctx->channel_count; ch++) { + accu = ctx->channel_outputs[ch]; + if (!accu) + continue; + bit = sample[ch / 8] & (1 << (ch % 8)); + g_string_append_c(accu, bit ? '1' : '0'); + } + } +} + +static int receive(const struct sr_output *o, + const struct sr_datafeed_packet *packet, GString **out) +{ + struct context *ctx; + + *out = NULL; + + if (!o || !o->sdi || !o->priv) + return SR_ERR_ARG; + + ctx = o->priv; + + switch (packet->type) { + case SR_DF_LOGIC: + process_logic(ctx, packet->payload); + break; + case SR_DF_END: + *out = wavedrom_render(ctx); + break; + } + + return SR_OK; +} + static int init(struct sr_output *o, GHashTable *options) { struct context *ctx; @@ -125,56 +198,6 @@ static int cleanup(struct sr_output *o) return SR_OK; } -static void process_logic(const struct context *ctx, - const struct sr_datafeed_logic *logic) -{ - size_t sample_count, ch, i; - uint8_t *sample; - - sample_count = logic->length / logic->unitsize; - - /* - * Extract the logic bits for each channel and store them - * as wavedrom letters (1/0) in each channel's text string. - */ - for (ch = 0; ch < ctx->channel_count; ch++) { - if (ctx->channels[ch]) { - for (i = 0; i < sample_count; i++) { - sample = logic->data + i * logic->unitsize; - - if (ctx->channel_outputs[ch]) { - g_string_append_c(ctx->channel_outputs[ch], - sample[ch / 8] & (1 << (ch % 8)) ? '1' : '0'); - } - } - } - } -} - -static int receive(const struct sr_output *o, - const struct sr_datafeed_packet *packet, GString **out) -{ - struct context *ctx; - - *out = NULL; - - if (!o || !o->sdi || !o->priv) - return SR_ERR_ARG; - - ctx = o->priv; - - switch (packet->type) { - case SR_DF_LOGIC: - process_logic(ctx, packet->payload); - break; - case SR_DF_END: - *out = wavedrom_render(ctx); - break; - } - - return SR_OK; -} - SR_PRIV struct sr_output_module output_wavedrom = { .id = "wavedrom", .name = "WaveDrom",