]> sigrok.org Git - libsigrokdecode.git/blame - decoders/ir_irmp/pd.py
ir_irmp: introduce IRMP based decoder for infrared signals
[libsigrokdecode.git] / decoders / ir_irmp / pd.py
CommitLineData
4032dedd
GS
1##
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.
6##
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.
11##
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/>.
14##
15
16import sigrokdecode as srd
17
18#from .lists import *
19
20from .IrmpPythonWrap import IrmpWrap
21
22class SamplerateError(Exception):
23 pass
24
25class Decoder(srd.Decoder):
26 api_version = 3
27 id = 'ir_irmp'
28 name = 'IR IRMP'
29 longname = 'IR IRMP multi protocol decoder'
30 desc = 'IRMP - multi protocol infrared decoder with support for many IR protocols by Frank M. (ukw)'
31 license = 'gplv2+'
32 inputs = ['logic']
33 outputs = []
34 tags = ['IR']
35 channels = (
36 {'id': 'ir', 'name': 'IR', 'desc': 'Data line'},
37 )
38 options = (
39 {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low',
40 'values': ('active-low', 'active-high')},
41#
42# {'id': 'cd_freq', 'desc': 'Carrier Frequency', 'default': 0},
43 )
44 annotations = (
45 ('packet', 'Packet'),
46 ('debug', 'Debug'),
47 )
48 annotation_rows = (
49 ('packets', 'IR Packets', (0,)),
50 ('debug', 'Debug', (1,)),
51 )
52 irmp = IrmpWrap()
53
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']
62
63
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 ''}",
70 f"C:{cm:x}",
71 ]])
72
73 def __init__(self):
74 self.irmp = Decoder.irmp
75 self.reset()
76
77 def reset(self):
78 self.irmp.Reset()
79
80 def start(self):
81 self.out_ann = self.register(srd.OUTPUT_ANN)
82
83 def metadata(self, key, value):
84 if key == srd.SRD_CONF_SAMPLERATE:
85 self.samplerate = value
86
87
88 def decode(self):
89 if not self.samplerate:
90 raise SamplerateError('Cannot decode without samplerate.')
91
92
93 if (self.samplerate % self.irmp.GetSampleRate()) != 0:
94 raise SamplerateError(f'samplerate has to be multple of {self.irmp.GetSampleRate()}' )
95
96 self.subSample = int(self.samplerate / self.irmp.GetSampleRate())
97 sampleSkip = self.subSample
98 #self.reset()
99 #print (f" startdecode: samplenum {self.samplenum} rate: {self.samplerate} subsample {self.subSample}")
100 # cd_count = None
101 # if self.options['cd_freq']:
102 # cd_count = int(self.samplerate / self.options['cd_freq']) + 1
103
104 self.active = 0 if self.options['polarity'] == 'active-low' else 1
105
106 (ir,) = self.wait([{'skip' : sampleSkip}])
107 i = 0
108
109 while True:
110 ##### todo: check if ir carrier frequency detection can be used
111 #
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.
125 # if cd_count:
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:
130 # continue
131 # prev_ir = cur_ir
132 # self.ir = cur_ir
133 # else:
134 # (self.ir,) = self.wait({0: 'e'})
135 #
136 #print (f"samplenum {self.samplenum}")
137 #if i%100 == 0:
138 # self.put(self.samplenum, self.samplenum+10, self.out_ann,
139 # [1, [ f"{self.samplenum} - {i}",]])
140
141 if self.active == 1:
142 ir = 1 - ir
143
144 if self.irmp.AddSample(ir):
145 data = self.irmp.GetData()
146 self.putIr(data)
147 i = i + 1
148 (ir,) = self.wait([{'skip' : sampleSkip}])
149