X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=decoders%2Fir_nec%2Fpd.py;h=02d70a9c299aa36ce5fffcb6fc41075715cfeb9c;hp=93b398b59ccfc1dfb481e314aa40d6379b476482;hb=fb1870b00fe4490eb9d4cd2b777629321416f763;hpb=4539e9ca58966ce3c9cad4801b16c315e86ace01 diff --git a/decoders/ir_nec/pd.py b/decoders/ir_nec/pd.py index 93b398b..02d70a9 100644 --- a/decoders/ir_nec/pd.py +++ b/decoders/ir_nec/pd.py @@ -38,6 +38,7 @@ class Decoder(srd.Decoder): options = ( {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low', 'values': ('active-low', 'active-high')}, + {'id': 'cd_freq', 'desc': 'Carrier Frequency', 'default': 0}, ) annotations = ( ('bit', 'Bit'), @@ -99,6 +100,9 @@ class Decoder(srd.Decoder): '%s' % btn[1]]]) def __init__(self): + self.reset() + + def reset(self): self.state = 'IDLE' self.ss_bit = self.ss_start = self.ss_other_edge = self.ss_remote = 0 self.data = self.count = self.active = None @@ -108,24 +112,25 @@ class Decoder(srd.Decoder): self.out_ann = self.register(srd.OUTPUT_ANN) self.active = 0 if self.options['polarity'] == 'active-low' else 1 - # Set the initial (assumed) value of the pin as per user-config. - self.initial_pins = [1 if self.active == 0 else 0] - def metadata(self, key, value): if key == srd.SRD_CONF_SAMPLERATE: self.samplerate = value - self.margin = int(self.samplerate * 0.0001) - 1 # 0.1ms + self.tolerance = 0.05 # +/-5% self.lc = int(self.samplerate * 0.0135) - 1 # 13.5ms self.rc = int(self.samplerate * 0.01125) - 1 # 11.25ms 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 + def compare_with_tolerance(self, measured, base): + return (measured >= base * (1 - self.tolerance) + and measured <= base * (1 + self.tolerance)) + def handle_bit(self, tick): ret = None - if tick in range(self.dazero - self.margin, self.dazero + self.margin): + if self.compare_with_tolerance(tick, self.dazero): ret = 0 - elif tick in range(self.daone - self.margin, self.daone + self.margin): + elif self.compare_with_tolerance(tick, self.daone): ret = 1 if ret in (0, 1): self.putb([0, ['%d' % ret]]) @@ -154,9 +159,36 @@ class Decoder(srd.Decoder): def decode(self): if not self.samplerate: raise SamplerateError('Cannot decode without samplerate.') + + cd_count = None + if self.options['cd_freq']: + cd_count = int(self.samplerate / self.options['cd_freq']) + 1 + prev_ir = None + while True: - # Wait for any edge (rising or falling). - (self.ir,) = self.wait({0: 'e'}) + # Detect changes in the presence of an active input signal. + # The decoder can either be fed an already filtered RX signal + # or optionally can detect the presence of a carrier. Periods + # of inactivity (signal changes slower than the carrier freq, + # if specified) pass on the most recently sampled level. This + # approach works for filtered and unfiltered input alike, and + # only slightly extends the active phase of input signals with + # carriers included by one period of the carrier frequency. + # IR based communication protocols can cope with this slight + # inaccuracy just fine by design. Enabling carrier detection + # on already filtered signals will keep the length of their + # active period, but will shift their signal changes by one + # carrier period before they get passed to decoding logic. + if cd_count: + (cur_ir,) = self.wait([{0: 'e'}, {'skip': cd_count}]) + if self.matched[0]: + cur_ir = self.active + if cur_ir == prev_ir: + continue + prev_ir = cur_ir + self.ir = cur_ir + else: + (self.ir,) = self.wait({0: 'e'}) if self.ir != self.active: # Save the non-active edge, then wait for the next edge. @@ -167,13 +199,13 @@ class Decoder(srd.Decoder): # State machine. if self.state == 'IDLE': - if b in range(self.lc - self.margin, self.lc + self.margin): + if self.compare_with_tolerance(b, self.lc): self.putpause('Long') self.putx([5, ['Leader code', 'Leader', 'LC', 'L']]) self.ss_remote = self.ss_start self.data = self.count = 0 self.state = 'ADDRESS' - elif b in range(self.rc - self.margin, self.rc + self.margin): + elif self.compare_with_tolerance(b, self.rc): self.putpause('Short') self.putstop(self.samplenum) self.samplenum += self.stop