uart: allow arbitrary sample positions for UART bit values (1-99%)
authorGerhard Sittig <gerhard.sittig@gmx.net>
Wed, 4 Dec 2019 20:21:03 +0000 (21:21 +0100)
committerUwe Hermann <uwe@hermann-uwe.de>
Mon, 16 Dec 2019 23:43:59 +0000 (00:43 +0100)
The previous implementation of the UART decoder used to sample bit values
strictly at the center position within a bit time. This commit introduces
support to sample bit values at arbitrary positions in the range of 1-99%
of the bit time. This allows to work around glitches in existing captures
as well as using the decoder for UART like protocols which don't sample
bit values at the center position (like EIB aka KNX).

This implementation is incomplete (on purpose). Although this version
improves the ability to extract data from captures, it also introduces
inaccuracies in the annotation positions for non-default values of the
sample point position. Addressing this issue is left for later, assuming
that it'll be a byproduct of another commit series that is being worked
on (general annotation position adjustment and stop bits support).

decoders/uart/pd.py

index 4ce6ef9dbe14a301a7b2a92f637f99cb51e1f317..9ffcb56e6d35cf06a1c7734e44086aefb2bca249 100644 (file)
@@ -114,6 +114,7 @@ class Decoder(srd.Decoder):
             'values': ('yes', 'no')},
         {'id': 'invert_tx', 'desc': 'Invert TX', 'default': 'no',
             'values': ('yes', 'no')},
+        {'id': 'sample_point', 'desc': 'Sample point (%)', 'default': 50},
         {'id': 'rx_packet_delim', 'desc': 'RX packet delimiter (decimal)',
             'default': -1},
         {'id': 'tx_packet_delim', 'desc': 'TX packet delimiter (decimal)',
@@ -224,12 +225,15 @@ class Decoder(srd.Decoder):
 
     def get_sample_point(self, rxtx, bitnum):
         # Determine absolute sample number of a bit slot's sample point.
-        # bitpos is the samplenumber which is in the middle of the
-        # specified UART bit (0 = start bit, 1..x = data, x+1 = parity bit
-        # (if used) or the first stop bit, and so on).
-        # The samples within bit are 0, 1, ..., (bit_width - 1), therefore
-        # index of the middle sample within bit window is (bit_width - 1) / 2.
-        bitpos = self.frame_start[rxtx] + (self.bit_width - 1) / 2.0
+        # Counts for UART bits start from 0 (0 = start bit, 1..x = data,
+        # x+1 = parity bit (if used) or the first stop bit, and so on).
+        # Accept a position in the range of 1.99% of the full bit width.
+        # Assume 50% for invalid input specs for backwards compatibility.
+        perc = self.options['sample_point'] or 50
+        if not perc or perc not in range(1, 100):
+            perc = 50
+        bitpos = (self.bit_width - 1) * perc / 100
+        bitpos += self.frame_start[rxtx]
         bitpos += bitnum * self.bit_width
         return bitpos