2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2014 Gump Yang <gump.yang@gmail.com>
5 ## Copyright (C) 2019 Rene Staffen
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.
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.
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/>.
21 from . import irmp_library
22 import sigrokdecode as srd
24 class SamplerateError(Exception):
27 class Decoder(srd.Decoder):
32 desc = 'IRMP infrared remote control multi protocol.'
38 {'id': 'ir', 'name': 'IR', 'desc': 'Data line'},
41 {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low',
42 'values': ('active-low', 'active-high')},
48 ('packets', 'IR Packets', (0,)),
51 def putframe(self, data):
52 '''Emit annotation for an IR frame.'''
54 # Cache result data fields in local variables. Get the ss/es
55 # timestamps, scaled to sample numbers.
57 name = data['proto_name']
58 addr = data['address']
60 repeat = data['repeat']
61 release = data['release']
62 ss = data['start'] * self.rate_factor
63 es = data['end'] * self.rate_factor
65 # Prepare display texts for several zoom levels.
66 # Implementor's note: Keep list lengths for flags aligned during
67 # maintenance. Make sure there are as many flags text variants
68 # as are referenced by annotation text variants. Differing list
69 # lengths or dynamic refs will severely complicate the logic.
70 rep_txts = ['repeat', 'rep', 'r']
71 rel_txts = ['release', 'rel', 'R']
72 flag_txts = [None,] * len(rep_txts)
73 for zoom in range(len(flag_txts)):
76 flag_txts[zoom].append(rep_txts[zoom])
78 flag_txts[zoom].append(rel_txts[zoom])
79 flag_txts = [' '.join(t) or '-' for t in flag_txts]
80 flg = flag_txts # Short name for .format() references.
82 'Protocol: {name} ({nr}), Address 0x{addr:04x}, Command: 0x{cmd:04x}, Flags: {flg[0]}'.format(**locals()),
83 'P: {name} ({nr}), Addr: 0x{addr:x}, Cmd: 0x{cmd:x}, Flg: {flg[1]}'.format(**locals()),
84 'P: {nr} A: 0x{addr:x} C: 0x{cmd:x} F: {flg[1]}'.format(**locals()),
85 'C:{cmd:x} A:{addr:x} {flg[2]}'.format(**locals()),
86 'C:{cmd:x}'.format(**locals()),
89 # Emit the annotation from details which were constructed above.
90 self.put(ss, es, self.out_ann, [0, txts])
93 self.irmp = irmp_library.IrmpLibrary()
94 self.lib_rate = self.irmp.get_sample_rate()
98 self.irmp.reset_state()
101 self.out_ann = self.register(srd.OUTPUT_ANN)
103 def metadata(self, key, value):
104 if key == srd.SRD_CONF_SAMPLERATE:
105 self.samplerate = value
108 if not self.samplerate:
109 raise SamplerateError('Cannot decode without samplerate.')
110 if self.samplerate % self.lib_rate:
111 raise SamplerateError('capture samplerate must be multiple of library samplerate ({})'.format(self.lib_rate))
112 self.rate_factor = int(self.samplerate / self.lib_rate)
114 self.active = 0 if self.options['polarity'] == 'active-low' else 1
119 if self.irmp.add_one_sample(ir):
120 data = self.irmp.get_result_data()
122 ir, = self.wait([{'skip': self.rate_factor}])