]> sigrok.org Git - libsigrokdecode.git/blame - decoders/ir_irmp/pd.py
parallel: rephrase word accumulation after reset introduction
[libsigrokdecode.git] / decoders / ir_irmp / pd.py
CommitLineData
4032dedd 1##
e8e8bec6
GS
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2014 Gump Yang <gump.yang@gmail.com>
5## Copyright (C) 2019 Rene Staffen
6##
4032dedd
GS
7## This program is free software; you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation; either version 2 of the License, or
10## (at your option) any later version.
11##
12## This program is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with this program; if not, see <http://www.gnu.org/licenses/>.
19##
20
e8e8bec6 21from . import irmp_library
4032dedd
GS
22import sigrokdecode as srd
23
4032dedd
GS
24class SamplerateError(Exception):
25 pass
26
f8c62753
GS
27class LibraryError(Exception):
28 pass
29
4032dedd
GS
30class Decoder(srd.Decoder):
31 api_version = 3
32 id = 'ir_irmp'
33 name = 'IR IRMP'
e8e8bec6
GS
34 longname = 'IR IRMP'
35 desc = 'IRMP infrared remote control multi protocol.'
4032dedd
GS
36 license = 'gplv2+'
37 inputs = ['logic']
38 outputs = []
39 tags = ['IR']
40 channels = (
41 {'id': 'ir', 'name': 'IR', 'desc': 'Data line'},
42 )
43 options = (
44 {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low',
45 'values': ('active-low', 'active-high')},
4032dedd
GS
46 )
47 annotations = (
48 ('packet', 'Packet'),
4032dedd
GS
49 )
50 annotation_rows = (
51 ('packets', 'IR Packets', (0,)),
4032dedd 52 )
4032dedd 53
e8e8bec6 54 def putframe(self, data):
8c3291c7
GS
55 '''Emit annotation for an IR frame.'''
56
57 # Cache result data fields in local variables. Get the ss/es
58 # timestamps, scaled to sample numbers.
e8e8bec6
GS
59 nr = data['proto_nr']
60 name = data['proto_name']
61 addr = data['address']
62 cmd = data['command']
63 repeat = data['repeat']
8c3291c7 64 release = data['release']
e8e8bec6
GS
65 ss = data['start'] * self.rate_factor
66 es = data['end'] * self.rate_factor
8c3291c7
GS
67
68 # Prepare display texts for several zoom levels.
69 # Implementor's note: Keep list lengths for flags aligned during
70 # maintenance. Make sure there are as many flags text variants
71 # as are referenced by annotation text variants. Differing list
72 # lengths or dynamic refs will severely complicate the logic.
73 rep_txts = ['repeat', 'rep', 'r']
74 rel_txts = ['release', 'rel', 'R']
75 flag_txts = [None,] * len(rep_txts)
76 for zoom in range(len(flag_txts)):
77 flag_txts[zoom] = []
78 if repeat:
79 flag_txts[zoom].append(rep_txts[zoom])
80 if release:
81 flag_txts[zoom].append(rel_txts[zoom])
82 flag_txts = [' '.join(t) or '-' for t in flag_txts]
83 flg = flag_txts # Short name for .format() references.
84 txts = [
85 'Protocol: {name} ({nr}), Address 0x{addr:04x}, Command: 0x{cmd:04x}, Flags: {flg[0]}'.format(**locals()),
86 'P: {name} ({nr}), Addr: 0x{addr:x}, Cmd: 0x{cmd:x}, Flg: {flg[1]}'.format(**locals()),
87 'P: {nr} A: 0x{addr:x} C: 0x{cmd:x} F: {flg[1]}'.format(**locals()),
88 'C:{cmd:x} A:{addr:x} {flg[2]}'.format(**locals()),
e8e8bec6 89 'C:{cmd:x}'.format(**locals()),
8c3291c7
GS
90 ]
91
92 # Emit the annotation from details which were constructed above.
93 self.put(ss, es, self.out_ann, [0, txts])
4032dedd
GS
94
95 def __init__(self):
f8c62753 96 self.irmp = None
4032dedd
GS
97 self.reset()
98
99 def reset(self):
f8c62753 100 self.want_reset = True
4032dedd
GS
101
102 def start(self):
103 self.out_ann = self.register(srd.OUTPUT_ANN)
104
105 def metadata(self, key, value):
106 if key == srd.SRD_CONF_SAMPLERATE:
107 self.samplerate = value
108
4032dedd 109 def decode(self):
f8c62753
GS
110 if not self.irmp:
111 try:
112 self.irmp = irmp_library.IrmpLibrary()
113 except Exception as e:
114 txt = e.args[0]
115 raise LibraryError(txt)
116 if self.irmp:
117 self.lib_rate = self.irmp.get_sample_rate()
118 if not self.irmp or not self.lib_rate:
119 raise LibraryError('Cannot access IRMP library. One instance limit exceeded?')
4032dedd
GS
120 if not self.samplerate:
121 raise SamplerateError('Cannot decode without samplerate.')
e8e8bec6 122 if self.samplerate % self.lib_rate:
f8c62753 123 raise SamplerateError('Capture samplerate must be multiple of library samplerate ({})'.format(self.lib_rate))
e8e8bec6 124 self.rate_factor = int(self.samplerate / self.lib_rate)
f8c62753
GS
125 if self.want_reset:
126 self.irmp.reset_state()
127 self.want_reset = False
4032dedd 128
4032dedd 129 self.active = 0 if self.options['polarity'] == 'active-low' else 1
e8e8bec6 130 ir, = self.wait()
4032dedd 131 while True:
4032dedd
GS
132 if self.active == 1:
133 ir = 1 - ir
e8e8bec6
GS
134 if self.irmp.add_one_sample(ir):
135 data = self.irmp.get_result_data()
136 self.putframe(data)
137 ir, = self.wait([{'skip': self.rate_factor}])