]> sigrok.org Git - libsigrokdecode.git/blobdiff - decoders/jitter/pd.py
license: remove FSF postal address from boiler plate license text
[libsigrokdecode.git] / decoders / jitter / pd.py
index bc5164da782014f4da2d4905c3854bfe01e6b36e..04a2577403094fa6f6aba83376973494a9e06229 100644 (file)
@@ -14,8 +14,7 @@
 ## GNU General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
 ##
 
 import sigrokdecode as srd
@@ -31,7 +30,7 @@ class SamplerateError(Exception):
     pass
 
 class Decoder(srd.Decoder):
-    api_version = 2
+    api_version = 3
     id = 'jitter'
     name = 'Jitter'
     longname = 'Timing jitter calculation'
@@ -59,12 +58,14 @@ class Decoder(srd.Decoder):
         ('clk_missed', 'Clock missed', (1,)),
         ('sig_missed', 'Signal missed', (2,)),
     )
+    binary = (
+        ('ascii-float', 'Jitter values as newline-separated ASCII floats'),
+    )
 
-    def __init__(self, **kwargs):
+    def __init__(self):
         self.state = 'CLK'
         self.samplerate = None
-        self.oldpin = None
-        self.oldclk = self.oldsig = None
+        self.oldclk, self.oldsig = 0, 0
         self.clk_start = None
         self.sig_start = None
         self.clk_missed = 0
@@ -74,6 +75,7 @@ class Decoder(srd.Decoder):
         self.clk_edge = edge_detector[self.options['clk_polarity']]
         self.sig_edge = edge_detector[self.options['sig_polarity']]
         self.out_ann = self.register(srd.OUTPUT_ANN)
+        self.out_binary = self.register(srd.OUTPUT_BINARY)
         self.out_clk_missed = self.register(srd.OUTPUT_META,
             meta=(int, 'Clock missed', 'Clock transition missed'))
         self.out_sig_missed = self.register(srd.OUTPUT_META,
@@ -87,93 +89,106 @@ class Decoder(srd.Decoder):
     def putx(self, delta):
         # Adjust granularity.
         if delta == 0 or delta >= 1:
-            delta_s = u"%us" % (delta)
+            delta_s = '%.1fs' % (delta)
         elif delta <= 1e-12:
-            delta_s = u"%.1ffs" % (delta * 1e15)
+            delta_s = '%.1ffs' % (delta * 1e15)
         elif delta <= 1e-9:
-            delta_s = u"%.1fps" % (delta * 1e12)
+            delta_s = '%.1fps' % (delta * 1e12)
         elif delta <= 1e-6:
-            delta_s = u"%.1fns" % (delta * 1e9)
+            delta_s = '%.1fns' % (delta * 1e9)
         elif delta <= 1e-3:
-            delta_s = u"%.1fμs" % (delta * 1e6)
+            delta_s = '%.1fμs' % (delta * 1e6)
         else:
-            delta_s = u"%.1fms" % (delta * 1e3)
+            delta_s = '%.1fms' % (delta * 1e3)
 
         self.put(self.clk_start, self.sig_start, self.out_ann, [0, [delta_s]])
 
+    # Helper function for ASCII float jitter values (one value per line).
+    def putb(self, delta):
+        if delta is None:
+            return
+        # Format the delta to an ASCII float value terminated by a newline.
+        x = str(delta) + '\n'
+        self.put(self.clk_start, self.sig_start, self.out_binary,
+                 [0, x.encode('UTF-8')])
+
     # Helper function for missed clock and signal annotations.
     def putm(self, data):
         self.put(self.samplenum, self.samplenum, self.out_ann, data)
 
-    def decode(self, ss, es, data):
+    def handle_clk(self, clk, sig):
+        if self.clk_start == self.samplenum:
+            # Clock transition already treated.
+            # We have done everything we can with this sample.
+            return True
+
+        if self.clk_edge(self.oldclk, clk):
+            # Clock edge found.
+            # We note the sample and move to the next state.
+            self.clk_start = self.samplenum
+            self.state = 'SIG'
+            return False
+        else:
+            if self.sig_start is not None \
+               and self.sig_start != self.samplenum \
+               and self.sig_edge(self.oldsig, sig):
+                # If any transition in the resulting signal
+                # occurs while we are waiting for a clock,
+                # we increase the missed signal counter.
+                self.sig_missed += 1
+                self.put(self.samplenum, self.samplenum, self.out_sig_missed, self.sig_missed)
+                self.putm([2, ['Missed signal', 'MS']])
+            # No clock edge found, we have done everything we
+            # can with this sample.
+            return True
+
+    def handle_sig(self, clk, sig):
+        if self.sig_start == self.samplenum:
+            # Signal transition already treated.
+            # We have done everything we can with this sample.
+            return True
+
+        if self.sig_edge(self.oldsig, sig):
+            # Signal edge found.
+            # We note the sample, calculate the jitter
+            # and move to the next state.
+            self.sig_start = self.samplenum
+            self.state = 'CLK'
+            # Calculate and report the timing jitter.
+            delta = (self.sig_start - self.clk_start) / self.samplerate
+            self.putx(delta)
+            self.putb(delta)
+            return False
+        else:
+            if self.clk_start != self.samplenum \
+               and self.clk_edge(self.oldclk, clk):
+                # If any transition in the clock signal
+                # occurs while we are waiting for a resulting
+                # signal, we increase the missed clock counter.
+                self.clk_missed += 1
+                self.put(self.samplenum, self.samplenum, self.out_clk_missed, self.clk_missed)
+                self.putm([1, ['Missed clock', 'MC']])
+            # No resulting signal edge found, we have done
+            # everything we can with this sample.
+            return True
+
+    def decode(self):
         if not self.samplerate:
             raise SamplerateError('Cannot decode without samplerate.')
-
-        for (self.samplenum, pins) in data:
-            # We are only interested in transitions.
-            if self.oldpin == pins:
-                continue
-
-            self.oldpin, (clk, sig) = pins, pins
-
-            if self.oldclk is None and self.oldsig is None:
-                self.oldclk, self.oldsig = clk, sig
+        while True:
+            # Wait for a transition on CLK and/or SIG.
+            clk, sig = self.wait([{0: 'e'}, {1: 'e'}])
 
             # State machine:
             # For each sample we can move 2 steps forward in the state machine.
             while True:
-
                 # Clock state has the lead.
                 if self.state == 'CLK':
-                    if self.clk_start == self.samplenum:
-                        # Clock transition already treated.
-                        # We have done everything we can with this sample.
+                    if self.handle_clk(clk, sig):
                         break
-                    else:
-                        if self.clk_edge(self.oldclk, clk) is True:
-                            # Clock edge found.
-                            # We note the sample and move to the next state.
-                            self.clk_start = self.samplenum
-                            self.state = 'SIG'
-                        else:
-                            if self.sig_start is not None \
-                               and self.sig_start != self.samplenum \
-                               and self.sig_edge(self.oldsig, sig) is True:
-                                # If any transition in the resulting signal
-                                # occurs while we are waiting for a clock,
-                                # we increase the missed signal counter.
-                                self.sig_missed += 1
-                                self.put(ss, self.samplenum, self.out_sig_missed, self.sig_missed)
-                                self.putm([2, ['Missed signal', 'MS']])
-                            # No clock edge found, we have done everything we
-                            # can with this sample.
-                            break
                 if self.state == 'SIG':
-                    if self.sig_start == self.samplenum:
-                        # Signal transition already treated.
-                        # We have done everything we can with this sample.
+                    if self.handle_sig(clk, sig):
                         break
-                    else:
-                        if self.sig_edge(self.oldsig, sig) is True:
-                            # Signal edge found.
-                            # We note the sample, calculate the jitter
-                            # and move to the next state.
-                            self.sig_start = self.samplenum
-                            self.state = 'CLK'
-                            # Calculate and report the timing jitter.
-                            self.putx((self.sig_start - self.clk_start) / self.samplerate)
-                        else:
-                            if self.clk_start != self.samplenum \
-                               and self.clk_edge(self.oldclk, clk) is True:
-                                # If any transition in the clock signal
-                                # occurs while we are waiting for a resulting
-                                # signal, we increase the missed clock counter.
-                                self.clk_missed += 1
-                                self.put(ss, self.samplenum, self.out_clk_missed, self.clk_missed)
-                                self.putm([1, ['Missed clock', 'MC']])
-                            # No resulting signal edge found, we have done
-                            # everything we can with this sample.
-                            break
 
             # Save current CLK/SIG values for the next round.
             self.oldclk, self.oldsig = clk, sig