]> sigrok.org Git - libsigrok.git/blobdiff - output/output_text.c
output_text: Mark trigger at correct position.
[libsigrok.git] / output / output_text.c
index 6e2d4f08f46b0d02e1fda80b936fed0d08811b16..6c2901ae086a9850ab6a54ae20c98c0f847457f7 100644 (file)
@@ -2,6 +2,7 @@
  * This file is part of the sigrok project.
  *
  * Copyright (C) 2010 Bert Vermeulen <bert@biot.com>
+ * Copyright (C) 2011 HÃ¥vard Espeland <gus@ping.uio.no>
  *
  * 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
 
 #define DEFAULT_BPL_BITS 64
 #define DEFAULT_BPL_HEX  192
+#define DEFAULT_BPL_ASCII 74
+
+enum outputmode {
+       MODE_BITS = 1,
+       MODE_HEX,
+       MODE_ASCII,
+};
 
 struct context {
        unsigned int num_enabled_probes;
@@ -39,6 +47,8 @@ struct context {
        uint8_t *linevalues;
        char *header;
        int mark_trigger;
+       uint64_t prevsample;
+       enum outputmode mode;
 };
 
 static void flush_linebufs(struct context *ctx, char *outbuf)
@@ -65,13 +75,20 @@ static void flush_linebufs(struct context *ctx, char *outbuf)
 
        /* Mark trigger with a ^ character. */
        if (ctx->mark_trigger != -1)
+       {
+               int space_offset = ctx->mark_trigger / 8;
+
+               if (ctx->mode == MODE_ASCII)
+                       space_offset = 0;
+
                sprintf(outbuf + strlen(outbuf), "T:%*s^\n",
-                       ctx->mark_trigger + (ctx->mark_trigger / 8), "");
+                       ctx->mark_trigger + space_offset, "");
+       }
 
        memset(ctx->linebuf, 0, i * ctx->linebuf_len);
 }
 
-static int init(struct output *o, int default_spl)
+static int init(struct output *o, int default_spl, enum outputmode mode)
 {
        struct context *ctx;
        struct probe *probe;
@@ -98,6 +115,7 @@ static int init(struct output *o, int default_spl)
        ctx->line_offset = 0;
        ctx->spl_cnt = 0;
        ctx->mark_trigger = -1;
+       ctx->mode = mode;
 
        if (o->param && o->param[0]) {
                ctx->samples_per_line = strtoul(o->param, NULL, 10);
@@ -179,7 +197,7 @@ static int event(struct output *o, int event_type, char **data_out,
 
 static int init_bits(struct output *o)
 {
-       return init(o, DEFAULT_BPL_BITS);
+       return init(o, DEFAULT_BPL_BITS, MODE_BITS);
 }
 
 static int data_bits(struct output *o, char *data_in, uint64_t length_in,
@@ -194,7 +212,11 @@ static int data_bits(struct output *o, char *data_in, uint64_t length_in,
        ctx = o->internal;
        max_linelen = MAX_PROBENAME_LEN + 3 + ctx->samples_per_line
                        + ctx->samples_per_line / 8;
-       outsize = (1 + (length_in / ctx->unitsize) / ctx->samples_per_line)
+        /*
+         * Calculate space needed for probes. Set aside 512 bytes for
+         * extra output, e.g. trigger.
+         */
+       outsize = 512 + (1 + (length_in / ctx->unitsize) / ctx->samples_per_line)
             * (ctx->num_enabled_probes * max_linelen);
 
        if (!(outbuf = calloc(1, outsize + 1)))
@@ -206,6 +228,10 @@ static int data_bits(struct output *o, char *data_in, uint64_t length_in,
                strncpy(outbuf, ctx->header, outsize);
                free(ctx->header);
                ctx->header = NULL;
+
+               /* Ensure first transition. */
+               memcpy(&ctx->prevsample, data_in, ctx->unitsize);
+               ctx->prevsample = ~ctx->prevsample;
        }
 
        if (length_in >= ctx->unitsize) {
@@ -247,7 +273,7 @@ static int data_bits(struct output *o, char *data_in, uint64_t length_in,
 
 static int init_hex(struct output *o)
 {
-       return init(o, DEFAULT_BPL_HEX);
+       return init(o, DEFAULT_BPL_HEX, MODE_HEX);
 }
 
 static int data_hex(struct output *o, char *data_in, uint64_t length_in,
@@ -310,6 +336,96 @@ static int data_hex(struct output *o, char *data_in, uint64_t length_in,
        return SIGROK_OK;
 }
 
+static int init_ascii(struct output *o)
+{
+       return init(o, DEFAULT_BPL_ASCII, MODE_ASCII);
+}
+
+static int data_ascii(struct output *o, char *data_in, uint64_t length_in,
+                    char **data_out, uint64_t *length_out)
+{
+       struct context *ctx;
+       unsigned int outsize, offset, p;
+       int max_linelen;
+       uint64_t sample;
+       char *outbuf;
+
+       ctx = o->internal;
+       max_linelen = MAX_PROBENAME_LEN + 3 + ctx->samples_per_line
+                       + ctx->samples_per_line / 8;
+        /*
+         * Calculate space needed for probes. Set aside 512 bytes for
+         * extra output, e.g. trigger.
+         */
+       outsize = 512 + (1 + (length_in / ctx->unitsize) / ctx->samples_per_line)
+            * (ctx->num_enabled_probes * max_linelen);
+
+       if (!(outbuf = calloc(1, outsize + 1)))
+               return SIGROK_ERR_MALLOC;
+
+       outbuf[0] = '\0';
+       if (ctx->header) {
+               /* The header is still here, this must be the first packet. */
+               strncpy(outbuf, ctx->header, outsize);
+               free(ctx->header);
+               ctx->header = NULL;
+       }
+
+       if (length_in >= ctx->unitsize) {
+               for (offset = 0; offset <= length_in - ctx->unitsize;
+                    offset += ctx->unitsize) {
+                       memcpy(&sample, data_in + offset, ctx->unitsize);
+
+                       char tmpval[ctx->num_enabled_probes];
+
+                       for (p = 0; p < ctx->num_enabled_probes; p++) {
+                               uint64_t curbit = (sample & ((uint64_t) 1 << p));
+                               uint64_t prevbit = (ctx->prevsample &
+                                               ((uint64_t) 1 << p));
+
+                               if (curbit < prevbit && ctx->line_offset > 0) {
+                                       ctx->linebuf[p * ctx->linebuf_len +
+                                               ctx->line_offset-1] = '\\';
+                               }
+
+                               if (curbit > prevbit) {
+                                       tmpval[p] = '/';
+                               } else {
+                                       if (curbit)
+                                               tmpval[p] = '"';
+                                       else
+                                               tmpval[p] = '.';
+                               }
+                       }
+
+                       /* End of line. */
+                       if (ctx->spl_cnt >= ctx->samples_per_line) {
+                               flush_linebufs(ctx, outbuf);
+                               ctx->line_offset = ctx->spl_cnt = 0;
+                               ctx->mark_trigger = -1;
+                       }
+
+                       for (p = 0; p < ctx->num_enabled_probes; p++) {
+                               ctx->linebuf[p * ctx->linebuf_len +
+                                            ctx->line_offset] = tmpval[p];
+                       }
+
+                       ctx->line_offset++;
+                       ctx->spl_cnt++;
+
+                       ctx->prevsample = sample;
+               }
+       } else {
+               g_message("short buffer (length_in=%" PRIu64 ")", length_in);
+       }
+
+       *data_out = outbuf;
+       *length_out = strlen(outbuf);
+
+       return SIGROK_OK;
+}
+
+
 struct output_format output_text_bits = {
        "bits",
        "Bits (takes argument, default 64)",
@@ -327,3 +443,12 @@ struct output_format output_text_hex = {
        data_hex,
        event,
 };
+
+struct output_format output_text_ascii = {
+       "ascii",
+       "ASCII (takes argument, default 74)",
+       DF_LOGIC,
+       init_ascii,
+       data_ascii,
+       event,
+};