2 * This file is part of the libsigrok project.
4 * Copyright (C) 2019 Marc Jacobi <obiwanjacobi@hotmail.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <libsigrok/libsigrok.h>
23 #include "libsigrok-internal.h"
25 #define LOG_PREFIX "output/wavedrom"
29 uint32_t channel_count;
30 // TODO: remove this, channels are available with each call
31 struct sr_channel **channels;
34 GString **channel_outputs;
37 // takes all data collected in context and
38 // renders it all to a JSON string.
39 static GString *wavedrom_render(const struct context *ctx)
42 GString *output = g_string_new("{ \"signal\": [");
44 char lastChar, currentChar;
46 for (ch = 0; ch < ctx->channel_count; ch++) {
47 if (!ctx->channel_outputs[ch])
51 g_string_append_printf(output,
52 "{ \"name\": \"%s\", \"wave\": \"", ctx->channels[ch]->name);
55 for (i = 0; i < ctx->channel_outputs[ch]->len; i++) {
56 currentChar = ctx->channel_outputs[ch]->str[i];
58 if (currentChar == lastChar) {
59 g_string_append_c(output, '.');
61 g_string_append_c(output, currentChar);
62 lastChar = currentChar;
65 if (ch < ctx->channel_count - 1) {
66 g_string_append(output, "\" },");
68 // last channel - no comma
69 g_string_append(output, "\" }");
74 g_string_append(output, "], \"config\": { \"skin\": \"narrow\" }}");
78 static int init(struct sr_output *o, GHashTable *options)
81 struct sr_channel *channel;
90 o->priv = ctx = g_malloc(sizeof(struct context));
92 ctx->channel_count = g_slist_length(o->sdi->channels);
93 ctx->channels = g_malloc(
94 sizeof(struct sr_channel) * ctx->channel_count);
95 ctx->channel_outputs = g_malloc(
96 sizeof(GString *) * ctx->channel_count);
98 for (i = 0, l = o->sdi->channels; l; l = l->next, i++) {
100 if (channel->enabled &&
101 channel->type == SR_CHANNEL_LOGIC) {
102 ctx->channels[i] = channel;
103 ctx->channel_outputs[i] = g_string_new(NULL);
105 ctx->channels[i] = NULL;
106 ctx->channel_outputs[i] = NULL;
113 static int cleanup(struct sr_output *o)
125 for (i = 0; i < ctx->channel_count; i++) {
126 if (ctx->channel_outputs[i])
127 g_string_free(ctx->channel_outputs[i], TRUE);
129 g_free(ctx->channel_outputs);
130 g_free(ctx->channels);
137 static void process_logic(const struct context *ctx,
138 const struct sr_datafeed_logic *logic)
140 unsigned int sample_count, ch, i;
143 sample_count = logic->length / logic->unitsize;
145 // extract the logic bits for each channel and
146 // store them as wavedrom letters (1/0) in each channel's string
147 for (ch = 0; ch < ctx->channel_count; ch++) {
148 if (ctx->channels[ch]) {
149 for (i = 0; i < sample_count; i++) {
150 sample = logic->data + i * logic->unitsize;
152 if (ctx->channel_outputs[ch]) {
153 g_string_append_c(ctx->channel_outputs[ch],
154 sample[ch / 8] & (1 << (ch % 8)) ? '1' : '0');
161 static int receive(const struct sr_output *o,
162 const struct sr_datafeed_packet *packet, GString **out)
168 if (!o || !o->sdi || !o->priv)
173 switch (packet->type) {
175 process_logic(ctx, packet->payload);
178 *out = wavedrom_render(ctx);
185 SR_PRIV struct sr_output_module output_wavedrom = {
188 .desc = "WaveDrom.com file format",
189 .exts = (const char *[]){"wavedrom", "json", NULL},