2 ## This program is free software; you can redistribute it and/or modify
3 ## it under the terms of the GNU General Public License as published by
4 ## the Free Software Foundation; either version 2 of the License, or
5 ## (at your option) any later version.
7 ## This program is distributed in the hope that it will be useful,
8 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ## GNU General Public License for more details.
12 ## You should have received a copy of the GNU General Public License
13 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
16 import sigrokdecode as srd
20 from .IrmpPythonWrap import IrmpWrap
22 class SamplerateError(Exception):
25 class Decoder(srd.Decoder):
29 longname = 'IR IRMP multi protocol decoder'
30 desc = 'IRMP - multi protocol infrared decoder with support for many IR protocols by Frank M. (ukw)'
36 {'id': 'ir', 'name': 'IR', 'desc': 'Data line'},
39 {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low',
40 'values': ('active-low', 'active-high')},
42 # {'id': 'cd_freq', 'desc': 'Carrier Frequency', 'default': 0},
49 ('packets', 'IR Packets', (0,)),
50 ('debug', 'Debug', (1,)),
54 def putIr(self, data):
55 ss = data['start'] * self.subSample
56 es = data['end'] * self.subSample
57 ad = data['data']['address']
58 pr = data['data']['protocol']
59 pn = data['data']['protocolName']
60 cm = data['data']['command']
61 repeat = data['data']['repeat']
64 # print(f" {self.samplenum} {ss} - {es} ({data['start']} - {data['end']})")
65 self.put(ss, es, self.out_ann,
66 [0, [ f"Protocol: {pn} ({pr}), Address 0x{ad:04x}, Command: 0x{cm:04x} {'repeated' if repeat else ''}",
67 f"P: {pn} ({pr}), Ad: 0x{ad:x}, Cmd: 0x{cm:x} {'rep' if repeat else ''}",
68 f"P: {pr} A: 0x{ad:x} C: 0x{cm:x} {'rep' if repeat else ''}",
69 f"C:{cm:x} A:{ad:x} {'r' if repeat else ''}",
74 self.irmp = Decoder.irmp
81 self.out_ann = self.register(srd.OUTPUT_ANN)
83 def metadata(self, key, value):
84 if key == srd.SRD_CONF_SAMPLERATE:
85 self.samplerate = value
89 if not self.samplerate:
90 raise SamplerateError('Cannot decode without samplerate.')
93 if (self.samplerate % self.irmp.GetSampleRate()) != 0:
94 raise SamplerateError(f'samplerate has to be multple of {self.irmp.GetSampleRate()}' )
96 self.subSample = int(self.samplerate / self.irmp.GetSampleRate())
97 sampleSkip = self.subSample
99 #print (f" startdecode: samplenum {self.samplenum} rate: {self.samplerate} subsample {self.subSample}")
101 # if self.options['cd_freq']:
102 # cd_count = int(self.samplerate / self.options['cd_freq']) + 1
104 self.active = 0 if self.options['polarity'] == 'active-low' else 1
106 (ir,) = self.wait([{'skip' : sampleSkip}])
110 ##### todo: check if ir carrier frequency detection can be used
112 # Detect changes in the presence of an active input signal.
113 # The decoder can either be fed an already filtered RX signal
114 # or optionally can detect the presence of a carrier. Periods
115 # of inactivity (signal changes slower than the carrier freq,
116 # if specified) pass on the most recently sampled level. This
117 # approach works for filtered and unfiltered input alike, and
118 # only slightly extends the active phase of input signals with
119 # carriers included by one period of the carrier frequency.
120 # IR based communication protocols can cope with this slight
121 # inaccuracy just fine by design. Enabling carrier detection
122 # on already filtered signals will keep the length of their
123 # active period, but will shift their signal changes by one
124 # carrier period before they get passed to decoding logic.
126 # (cur_ir,) = self.wait([{0: 'e'}, {'skip': cd_count}])
127 # if self.matched[0]:
128 # cur_ir = self.active
129 # if cur_ir == prev_ir:
134 # (self.ir,) = self.wait({0: 'e'})
136 #print (f"samplenum {self.samplenum}")
138 # self.put(self.samplenum, self.samplenum+10, self.out_ann,
139 # [1, [ f"{self.samplenum} - {i}",]])
144 if self.irmp.AddSample(ir):
145 data = self.irmp.GetData()
148 (ir,) = self.wait([{'skip' : sampleSkip}])