Since tastes and requirements might differ, introduce support for a
user specified character set in the construction of ASCII art graphs
of signal levels.  The syntax is "charset=<low><high>[<fall><rise>]",
the default remains backwards compatible with existing consumers.

In comparison to assuming a fixed character set, this change addresses
several distinct aspects:

Users can adjust the output for "higher visual contrast", or "straight
lines" instead of dotted patterns, or "increased difference in height"
for low and high signal levels, or "filled" (block like, "wall of text")
appearance of periods with high levels.  User adjustable characters are
needed, as no single fixed set can satisfy the differing expectations.
Perception of the output heavily depends on specific terminals and fonts
in use.

Then there is the issue of levels versus edges, and how their timing
relates.  By default edges are drawn at a point in time where the signal
was sampled and was deteremined to already _have_ changed and have
settled to the new level, which means that the position of edges in the
resulting graph might be off by up to one sample period.  Strictly
speaking, the available set of samples only contains levels, and does
not hint where exactly an edge might have occured.  Though this might be
considered rather nitpicky, representing the graph without edges does
better reflect the input data, and might simplify postprocessing.

Compare the previously only supported format (still the default, -O ascii):

  1:...................................................../""""""""""""""""""""
  1:""""""""""""""""""""""""""""""""\.........................................
  1:..........................................................................

to those example alternatives:

  $ sigrok-cli -i file.sr -O ascii:charset=_\"\\/
  1:_____________________________________________________/""""""""""""""""""""
  1:""""""""""""""""""""""""""""""""\_________________________________________
  1:__________________________________________________________________________

  $ sigrok-cli -i file.sr -O ascii:charset=_\"
  1:_____________________________________________________"""""""""""""""""""""
  1:""""""""""""""""""""""""""""""""__________________________________________
  1:__________________________________________________________________________

  $ sigrok-cli -i file.sr -O ascii:charset=_^
  1:_____________________________________________________^^^^^^^^^^^^^^^^^^^^^
  1:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__________________________________________
  1:__________________________________________________________________________

  $ sigrok-cli -i file.sr -O ascii:charset=_M
  1:_____________________________________________________MMMMMMMMMMMMMMMMMMMMM
  1:MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM__________________________________________
  1:__________________________________________________________________________

  $ sigrok-cli -i file.sr -O ascii:charset=_X
  1:_____________________________________________________XXXXXXXXXXXXXXXXXXXXX
  1:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX__________________________________________
  1:__________________________________________________________________________

Signed-off-by: Gerhard Sittig <gerhard.sit...@gmx.net>
---
 src/output/ascii.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/output/ascii.c b/src/output/ascii.c
index ba9acf9d5e99..b68f5726cdc9 100644
--- a/src/output/ascii.c
+++ b/src/output/ascii.c
@@ -28,6 +28,12 @@
 #define LOG_PREFIX "output/hex"
 
 #define DEFAULT_SAMPLES_PER_LINE 74
+/*
+ * The string looks ugly with escape characters, here is the readable
+ * version:  Use . and " for low and high bits, use \ and / to draw
+ * falling and rising edges respectively.
+ */
+#define DEFAULT_ASCII_CHARS ".\"\\/"
 
 struct context {
        unsigned int num_enabled_channels;
@@ -43,6 +49,8 @@ struct context {
        gboolean header_done;
        GString **lines;
        GString *header;
+       const char *charset;
+       gboolean edges;
 };
 
 static int init(struct sr_output *o, GHashTable *options)
@@ -59,6 +67,14 @@ static int init(struct sr_output *o, GHashTable *options)
        o->priv = ctx;
        ctx->trigger = -1;
        ctx->spl = g_variant_get_uint32(g_hash_table_lookup(options, "width"));
+       ctx->charset = g_strdup(g_variant_get_string(
+               g_hash_table_lookup(options, "charset"), NULL));
+       if (!ctx->charset || strlen(ctx->charset) < 2) {
+               if (ctx->charset)
+                       g_free((gpointer)ctx->charset);
+               ctx->charset = g_strdup(DEFAULT_ASCII_CHARS);
+       }
+       ctx->edges = strlen(ctx->charset) >= 4 ? TRUE : FALSE;
 
        for (l = o->sdi->channels; l; l = l->next) {
                ch = l->data;
@@ -133,6 +149,7 @@ static int receive(const struct sr_output *o, const struct 
sr_datafeed_packet *p
        int idx, offset, curbit, prevbit;
        uint64_t i, j;
        gchar *p, c;
+       size_t charidx;
 
        *out = NULL;
        if (!o || !o->sdi)
@@ -169,13 +186,12 @@ static int receive(const struct sr_output *o, const 
struct sr_datafeed_packet *p
                                curbit = *p & (1 << (idx % 8));
                                prevbit = (ctx->prev_sample[idx / 8] & 
((uint8_t) 1 << (idx % 8)));
 
-                               c = curbit ? '"' : '.';
-                               if (ctx->spl_cnt > 1) {
-                                       if (curbit < prevbit)
-                                               c = '\\';
-                                       else if (curbit > prevbit)
-                                               c = '/';
+                               charidx = curbit ? 1 : 0;
+                               if (ctx->edges && ctx->spl_cnt > 1) {
+                                       if (curbit != prevbit)
+                                               charidx += 2;
                                }
+                               c = ctx->charset[charidx];
                                g_string_append_c(ctx->lines[j], c);
 
                                if (ctx->spl_cnt == ctx->spl) {
@@ -228,6 +244,7 @@ static int cleanup(struct sr_output *o)
        for (i = 0; i < ctx->num_enabled_channels; i++)
                g_string_free(ctx->lines[i], TRUE);
        g_free(ctx->lines);
+       g_free((gpointer)ctx->charset);
        g_free(ctx);
        o->priv = NULL;
 
@@ -236,6 +253,7 @@ static int cleanup(struct sr_output *o)
 
 static struct sr_option options[] = {
        { "width", "Width", "Number of samples per line", NULL, NULL },
+       { "charset", "Charset", "Characters for 0/1 bits (and fall/rise 
edges)", NULL, NULL },
        ALL_ZERO
 };
 
@@ -244,6 +262,8 @@ static const struct sr_option *get_options(void)
        if (!options[0].def) {
                options[0].def = g_variant_new_uint32(DEFAULT_SAMPLES_PER_LINE);
                g_variant_ref_sink(options[0].def);
+               options[1].def = g_variant_new_string(DEFAULT_ASCII_CHARS);
+               g_variant_ref_sink(options[1].def);
        }
 
        return options;
-- 
1.9.1

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to