]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | import sigrokdecode as srd | |
17 | ||
18 | #from .lists import * | |
19 | ||
20 | from .IrmpPythonWrap import IrmpWrap | |
21 | ||
22 | class SamplerateError(Exception): | |
23 | pass | |
24 | ||
25 | class 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 |