]> sigrok.org Git - libsigrokdecode.git/commitdiff
ir_nec: improve robustness, present more data on invalid input
authorGerhard Sittig <redacted>
Sun, 26 Jul 2020 06:45:32 +0000 (08:45 +0200)
committerGerhard Sittig <redacted>
Sun, 26 Jul 2020 06:46:32 +0000 (08:46 +0200)
Don't terminate IR frame inspection when successfully decoded fields
fail the validity check. Reset internal state on long periods of idle
level instead (beware of the late detection of the STOP condition).

Unconditionally annotate received fields, and optionally amend them with
a warning annotation. It's unexpected to not see the address field value
at all just because the number was not acceptable for the potentially
incorrect protocol selection.

Rename a variable in the decode() routine. The 'b' identifier suggested
a bit value, but it was used for the pulse width.

decoders/ir_nec/pd.py

index c05e4744dc6a76c06f3007c2387040bcfa71a096..0c4987f6fe234dc56ec2fb6e8fca16db42940e03 100644 (file)
@@ -142,6 +142,7 @@ class Decoder(srd.Decoder):
         self.dazero = int(self.samplerate * 0.001125) - 1 # 1.125ms
         self.daone = int(self.samplerate * 0.00225) - 1 # 2.25ms
         self.stop = int(self.samplerate * 0.000652) - 1 # 0.652ms
+        self.idle_to = int(self.samplerate * 0.020) - 1 # 20ms, arbitrary choice
 
     def compare_with_tolerance(self, measured, base):
         return (measured >= base * (1 - self.tolerance)
@@ -179,11 +180,10 @@ class Decoder(srd.Decoder):
                 self.data = []
                 self.ss_bit = self.ss_start = self.samplenum
             return True
+        self.putd(show, want_len)
         if check and not valid:
             warn_show = bitpack(self.data)
             self.putx([Ann.WARN, ['{} error: 0x{:04X}'.format(name, warn_show)]])
-        else:
-            self.putd(show, want_len)
         self.data = []
         self.ss_bit = self.ss_start = self.samplenum
         return valid
@@ -232,17 +232,20 @@ class Decoder(srd.Decoder):
                 self.ss_other_edge = self.samplenum
                 continue
 
-            b = self.samplenum - self.ss_bit
+            # Reset internal state for long periods of idle level.
+            width = self.samplenum - self.ss_bit
+            if width >= self.idle_to and self.state != 'STOP':
+                self.reset()
 
             # State machine.
             if self.state == 'IDLE':
-                if self.compare_with_tolerance(b, self.lc):
+                if self.compare_with_tolerance(width, self.lc):
                     self.putpause('Long')
                     self.putx([Ann.LEADER_CODE, ['Leader code', 'Leader', 'LC', 'L']])
                     self.ss_remote = self.ss_start
                     self.data = []
                     self.state = 'ADDRESS'
-                elif self.compare_with_tolerance(b, self.rc):
+                elif self.compare_with_tolerance(width, self.rc):
                     self.putpause('Short')
                     self.putstop(self.samplenum)
                     self.samplenum += self.stop
@@ -250,23 +253,25 @@ class Decoder(srd.Decoder):
                     self.data = []
                 self.ss_bit = self.ss_start = self.samplenum
             elif self.state == 'ADDRESS':
-                self.handle_bit(b)
+                self.handle_bit(width)
                 if len(self.data) == want_addr_len:
                     self.data_ok(False, want_addr_len)
                     self.state = 'COMMAND' if self.is_extended else 'ADDRESS#'
             elif self.state == 'ADDRESS#':
-                self.handle_bit(b)
+                self.handle_bit(width)
                 if len(self.data) == 16:
-                    self.state = 'COMMAND' if self.data_ok(True, 8) else 'IDLE'
+                    self.data_ok(True, 8)
+                    self.state = 'COMMAND'
             elif self.state == 'COMMAND':
-                self.handle_bit(b)
+                self.handle_bit(width)
                 if len(self.data) == 8:
                     self.data_ok(False, 8)
                     self.state = 'COMMAND#'
             elif self.state == 'COMMAND#':
-                self.handle_bit(b)
+                self.handle_bit(width)
                 if len(self.data) == 16:
-                    self.state = 'STOP' if self.data_ok(True, 8) else 'IDLE'
+                    self.data_ok(True, 8)
+                    self.state = 'STOP'
             elif self.state == 'STOP':
                 self.putstop(self.ss_bit)
                 self.putremote()