]> sigrok.org Git - libsigrok.git/blobdiff - src/output/vcd.c
Doxyfile_internal: Fix various settings and paths.
[libsigrok.git] / src / output / vcd.c
index db77a7adeddf09cb37c6c6be9b7745a4de69d6c4..3de3dcde37b3a044679ed745e498433c987aa047 100644 (file)
@@ -31,7 +31,7 @@ struct context {
        int num_enabled_channels;
        uint8_t *prevsample;
        gboolean header_done;
-       int period;
+       uint64_t period;
        int *channel_index;
        uint64_t samplerate;
        uint64_t samplecount;
@@ -78,6 +78,38 @@ static int init(struct sr_output *o, GHashTable *options)
        return SR_OK;
 }
 
+/*
+ * VCD can only handle 1/10/100 factors in the s to fs range. Find a
+ * suitable timescale which satisfies this resolution constraint, yet
+ * won't result in excessive overhead.
+ */
+static uint64_t get_timescale_freq(uint64_t samplerate)
+{
+       uint64_t timescale;
+       int max_up_scale;
+
+       /* Go to the next full decade. */
+       timescale = 1;
+       while (timescale < samplerate) {
+               timescale *= 10;
+       }
+
+       /*
+        * Avoid loss of precision, go up a few more decades when needed.
+        * For example switch to 10GHz timescale when samplerate is 400MHz.
+        * Stop after at most factor 100 to not loop endlessly for odd
+        * samplerates, yet provide good enough accuracy.
+        */
+       max_up_scale = 2;
+       while (max_up_scale--) {
+               if (timescale / samplerate * samplerate == timescale)
+                       break;
+               timescale *= 10;
+       }
+
+       return timescale;
+}
+
 static GString *gen_header(const struct sr_output *o)
 {
        struct context *ctx;
@@ -96,13 +128,13 @@ static GString *gen_header(const struct sr_output *o)
        /* timestamp */
        t = time(NULL);
        timestamp = g_strdup(ctime(&t));
-       timestamp[strlen(timestamp)-1] = 0;
+       timestamp[strlen(timestamp) - 1] = 0;
        g_string_printf(header, "$date %s $end\n", timestamp);
        g_free(timestamp);
 
        /* generator */
        g_string_append_printf(header, "$version %s %s $end\n",
-                       PACKAGE_NAME, SR_PACKAGE_VERSION_STRING);
+                       PACKAGE_NAME, sr_package_version_string_get());
        g_string_append_printf(header, "$comment\n  Acquisition with "
                        "%d/%d channels", ctx->num_enabled_channels, num_channels);
 
@@ -121,13 +153,7 @@ static GString *gen_header(const struct sr_output *o)
        g_string_append_printf(header, "\n$end\n");
 
        /* timescale */
-       /* VCD can only handle 1/10/100 (s - fs), so scale up first */
-       if (ctx->samplerate > SR_MHZ(1))
-               ctx->period = SR_GHZ(1);
-       else if (ctx->samplerate > SR_KHZ(1))
-               ctx->period = SR_MHZ(1);
-       else
-               ctx->period = SR_KHZ(1);
+       ctx->period = get_timescale_freq(ctx->samplerate);
        frequency_s = sr_period_string(1, ctx->period);
        g_string_append_printf(header, "$timescale %s $end\n", frequency_s);
        g_free(frequency_s);
@@ -200,7 +226,16 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
                        timestamp_written = FALSE;
 
                        for (p = 0; p < ctx->num_enabled_channels; p++) {
-                               index = ctx->channel_index[p];
+                               /*
+                                * TODO Check whether the mapping from
+                                * data image positions to channel numbers
+                                * is required. Experiments suggest that
+                                * the data image "is dense", and packs
+                                * bits of enabled channels, and leaves no
+                                * room for positions of disabled channels.
+                                */
+                               /* index = ctx->channel_index[p]; */
+                               index = p;
 
                                curbit = ((unsigned)sample[index / 8]
                                                >> (index % 8)) & 1;
@@ -261,7 +296,7 @@ static int cleanup(struct sr_output *o)
 struct sr_output_module output_vcd = {
        .id = "vcd",
        .name = "VCD",
-       .desc = "Value Change Dump",
+       .desc = "Value Change Dump data",
        .exts = (const char*[]){"vcd", NULL},
        .flags = 0,
        .options = NULL,