Factor out the code which generates a textual representation for the
numeric values that were communicated via UART bit patterns.  Make the
width of the output text depend on the number of bits in the UART frame
(five to nine) instead of assuming bytes of exactly eight bits.

Fix other minor issues while we are here:  Nine bits result in a number
range of 0 to 511 (not 512).  ASCII codes 30 and 31 are non-printables.
The previous implementation skipped a significant leading digit in the
octal representation.

Signed-off-by: Gerhard Sittig <gerhard.sit...@gmx.net>
---
 decoders/uart/pd.py | 65 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 13 deletions(-)

diff --git a/decoders/uart/pd.py b/decoders/uart/pd.py
index be0e7c7f2d7e..e8e050105fc3 100644
--- a/decoders/uart/pd.py
+++ b/decoders/uart/pd.py
@@ -31,7 +31,7 @@
  - 'STARTBIT': The data is the (integer) value of the start bit (0/1).
  - 'DATA': This is always a tuple containing two items:
    - 1st item: the (integer) value of the UART data. Valid values
-     range from 0 to 512 (as the data can be up to 9 bits in size).
+     range from 0 to 511 (as the data can be up to 9 bits in size).
    - 2nd item: the list of individual data bits and their ss/es numbers.
  - 'PARITYBIT': The data is the (integer) value of the parity bit (0/1).
  - 'STOPBIT': The data is the (integer) value of the stop bit (0 or 1).
@@ -272,18 +272,10 @@ def get_data_bits(self, rxtx, signal):
         self.putpx(rxtx, ['DATA', rxtx,
             (self.datavalue[rxtx], self.databits[rxtx])])
 
-        b, f = self.datavalue[rxtx], self.options['format']
-        if f == 'ascii':
-            c = chr(b) if b in range(30, 126 + 1) else '[%02X]' % b
-            self.putx(rxtx, [rxtx, [c]])
-        elif f == 'dec':
-            self.putx(rxtx, [rxtx, [str(b)]])
-        elif f == 'hex':
-            self.putx(rxtx, [rxtx, [hex(b)[2:].zfill(2).upper()]])
-        elif f == 'oct':
-            self.putx(rxtx, [rxtx, [oct(b)[2:].zfill(3)]])
-        elif f == 'bin':
-            self.putx(rxtx, [rxtx, [bin(b)[2:].zfill(8)]])
+        b = self.datavalue[rxtx]
+        formatted = self.format_value(b)
+        if formatted is not None:
+            self.putx(rxtx, [rxtx, [formatted]])
 
         formatted = self.format_bytes(b)
         self.putbin(rxtx, [rxtx, formatted])
@@ -291,6 +283,53 @@ def get_data_bits(self, rxtx, signal):
 
         self.databits[rxtx] = []
 
+    def format_value(self, v):
+        """Format value 'v' according to configured options.
+
+        Reflects the user selected kind of representation, as well as
+        the number of data bits in the UART frames.
+        """
+
+        fmt, bits = self.options['format'], self.options['num_data_bits']
+
+        # assume "is printable" for values from 32 to including 126,
+        # below 32 is "control" and thus not printable, above 127 is
+        # "not ASCII" in its strict sense, 127 (DEL) is not printable,
+        # fall back to hex representation for non-printables
+        if fmt == 'ascii':
+            if v in range(32, 126 + 1):
+                return chr(v)
+            hexfmt = "[{:02X}]" if bits <= 8 else "[{:03X}]"
+            return hexfmt.format(v)
+
+        # mere number to text conversion without prefix and padding
+        # for the "decimal" output format
+        if fmt == 'dec':
+            return "{:d}".format(v)
+
+        # padding with leading zeroes for hex/oct/bin formats, but
+        # without a prefix for density -- since the format is user
+        # specified, there is no ambiguity
+        if fmt == 'hex':
+            digits = (bits + 4 - 1) // 4
+            fmtchar = "X"
+        elif fmt == 'oct':
+            digits = (bits + 3 - 1) // 3
+            fmtchar = "o"
+        elif fmt == 'bin':
+            digits = bits
+            fmtchar = "b"
+        else:
+            fmtchar = None
+        if fmtchar is not None:
+            fmt = "{{:0{:d}{:s}}}".format(digits, fmtchar)
+            return fmt.format(v)
+
+        # support for more formatting variants can go here
+
+        # UNREACH
+        return None
+
     def format_bytes(self, b):
         """Format data to either one or two bytes (5-8, and 9 bits)."""
         bits = self.options['num_data_bits']
-- 
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