]>
Commit | Line | Data |
---|---|---|
914f0b99 UH |
1 | ## |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2014 Uwe Hermann <uwe@hermann-uwe.de> | |
5 | ## | |
6 | ## This program is free software; you can redistribute it and/or modify | |
7 | ## it under the terms of the GNU General Public License as published by | |
8 | ## the Free Software Foundation; either version 2 of the License, or | |
9 | ## (at your option) any later version. | |
10 | ## | |
11 | ## This program is distributed in the hope that it will be useful, | |
12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | ## GNU General Public License for more details. | |
15 | ## | |
16 | ## You should have received a copy of the GNU General Public License | |
4539e9ca | 17 | ## along with this program; if not, see <http://www.gnu.org/licenses/>. |
914f0b99 UH |
18 | ## |
19 | ||
20 | import sigrokdecode as srd | |
21 | from .lists import * | |
22 | ||
21cda951 UH |
23 | class SamplerateError(Exception): |
24 | pass | |
25 | ||
914f0b99 | 26 | class Decoder(srd.Decoder): |
6eb8f524 | 27 | api_version = 3 |
914f0b99 UH |
28 | id = 'ir_rc5' |
29 | name = 'IR RC-5' | |
30 | longname = 'IR RC-5' | |
31 | desc = 'RC-5 infrared remote control protocol.' | |
32 | license = 'gplv2+' | |
33 | inputs = ['logic'] | |
6cbba91f | 34 | outputs = [] |
d6d8a8a4 | 35 | tags = ['IR'] |
6a15597a | 36 | channels = ( |
914f0b99 | 37 | {'id': 'ir', 'name': 'IR', 'desc': 'IR data line'}, |
da9bcbd9 | 38 | ) |
d1e2129c BV |
39 | options = ( |
40 | {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-low', | |
41 | 'values': ('active-low', 'active-high')}, | |
42 | {'id': 'protocol', 'desc': 'Protocol type', 'default': 'standard', | |
43 | 'values': ('standard', 'extended')}, | |
44 | ) | |
da9bcbd9 BV |
45 | annotations = ( |
46 | ('bit', 'Bit'), | |
47 | ('startbit1', 'Startbit 1'), | |
48 | ('startbit2', 'Startbit 2'), | |
49 | ('togglebit-0', 'Toggle bit 0'), | |
50 | ('togglebit-1', 'Toggle bit 1'), | |
51 | ('address', 'Address'), | |
52 | ('command', 'Command'), | |
53 | ) | |
914f0b99 UH |
54 | annotation_rows = ( |
55 | ('bits', 'Bits', (0,)), | |
56 | ('fields', 'Fields', (1, 2, 3, 4, 5, 6)), | |
57 | ) | |
58 | ||
92b7b49f | 59 | def __init__(self): |
10aeb8ea GS |
60 | self.reset() |
61 | ||
62 | def reset(self): | |
914f0b99 | 63 | self.samplerate = None |
486b19ce | 64 | self.edges, self.bits, self.ss_es_bits = [], [], [] |
914f0b99 UH |
65 | self.state = 'IDLE' |
66 | ||
67 | def start(self): | |
68 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
681bad2a | 69 | self.next_edge = 'l' if self.options['polarity'] == 'active-low' else 'h' |
914f0b99 UH |
70 | |
71 | def metadata(self, key, value): | |
72 | if key == srd.SRD_CONF_SAMPLERATE: | |
73 | self.samplerate = value | |
74 | # One bit: 1.78ms (one half low, one half high). | |
75 | self.halfbit = int((self.samplerate * 0.00178) / 2.0) | |
76 | ||
77 | def putb(self, bit1, bit2, data): | |
486b19ce | 78 | ss, es = self.ss_es_bits[bit1][0], self.ss_es_bits[bit2][1] |
914f0b99 UH |
79 | self.put(ss, es, self.out_ann, data) |
80 | ||
81 | def handle_bits(self): | |
82 | a, c, b = 0, 0, self.bits | |
83 | # Individual raw bits. | |
84 | for i in range(14): | |
85 | if i == 0: | |
86 | ss = max(0, self.bits[0][0] - self.halfbit) | |
87 | else: | |
486b19ce | 88 | ss = self.ss_es_bits[i - 1][1] |
914f0b99 | 89 | es = self.bits[i][0] + self.halfbit |
486b19ce | 90 | self.ss_es_bits.append([ss, es]) |
914f0b99 UH |
91 | self.putb(i, i, [0, ['%d' % self.bits[i][1]]]) |
92 | # Bits[0:0]: Startbit 1 | |
93 | s = ['Startbit1: %d' % b[0][1], 'SB1: %d' % b[0][1], 'SB1', 'S1', 'S'] | |
94 | self.putb(0, 0, [1, s]) | |
95 | # Bits[1:1]: Startbit 2 | |
96 | ann_idx = 2 | |
97 | s = ['Startbit2: %d' % b[1][1], 'SB2: %d' % b[1][1], 'SB2', 'S2', 'S'] | |
98 | if self.options['protocol'] == 'extended': | |
99 | s = ['CMD[6]#: %d' % b[1][1], 'C6#: %d' % b[1][1], 'C6#', 'C#', 'C'] | |
100 | ann_idx = 6 | |
101 | self.putb(1, 1, [ann_idx, s]) | |
102 | # Bits[2:2]: Toggle bit | |
103 | s = ['Togglebit: %d' % b[2][1], 'Toggle: %d' % b[2][1], | |
104 | 'TB: %d' % b[2][1], 'TB', 'T'] | |
105 | self.putb(2, 2, [3 if b[2][1] == 0 else 4, s]) | |
106 | # Bits[3:7]: Address (MSB-first) | |
107 | for i in range(5): | |
108 | a |= (b[3 + i][1] << (4 - i)) | |
109 | x = system.get(a, ['Unknown', 'Unk']) | |
110 | s = ['Address: %d (%s)' % (a, x[0]), 'Addr: %d (%s)' % (a, x[1]), | |
111 | 'Addr: %d' % a, 'A: %d' % a, 'A'] | |
112 | self.putb(3, 7, [5, s]) | |
113 | # Bits[8:13]: Command (MSB-first) | |
114 | for i in range(6): | |
115 | c |= (b[8 + i][1] << (5 - i)) | |
116 | if self.options['protocol'] == 'extended': | |
117 | inverted_bit6 = 1 if b[1][1] == 0 else 0 | |
118 | c |= (inverted_bit6 << 6) | |
119 | cmd_type = 'VCR' if x[1] in ('VCR1', 'VCR2') else 'TV' | |
120 | x = command[cmd_type].get(c, ['Unknown', 'Unk']) | |
121 | s = ['Command: %d (%s)' % (c, x[0]), 'Cmd: %d (%s)' % (c, x[1]), | |
122 | 'Cmd: %d' % c, 'C: %d' % c, 'C'] | |
123 | self.putb(8, 13, [6, s]) | |
124 | ||
125 | def edge_type(self): | |
126 | # Categorize according to distance from last edge (short/long). | |
127 | distance = self.samplenum - self.edges[-1] | |
128 | s, l, margin = self.halfbit, self.halfbit * 2, int(self.halfbit / 2) | |
129 | if distance in range(l - margin, l + margin + 1): | |
130 | return 'l' | |
131 | elif distance in range(s - margin, s + margin + 1): | |
132 | return 's' | |
133 | else: | |
16211e24 UH |
134 | return 'e' # Error, invalid edge distance. |
135 | ||
136 | def reset_decoder_state(self): | |
486b19ce | 137 | self.edges, self.bits, self.ss_es_bits = [], [], [] |
16211e24 | 138 | self.state = 'IDLE' |
914f0b99 | 139 | |
6eb8f524 | 140 | def decode(self): |
21cda951 UH |
141 | if not self.samplerate: |
142 | raise SamplerateError('Cannot decode without samplerate.') | |
6eb8f524 | 143 | while True: |
914f0b99 | 144 | |
681bad2a | 145 | (self.ir,) = self.wait({0: self.next_edge}) |
914f0b99 UH |
146 | |
147 | # State machine. | |
148 | if self.state == 'IDLE': | |
fcbd6336 | 149 | bit = 1 |
914f0b99 | 150 | self.edges.append(self.samplenum) |
fcbd6336 | 151 | self.bits.append([self.samplenum, bit]) |
914f0b99 | 152 | self.state = 'MID1' |
681bad2a | 153 | self.next_edge = 'l' if self.ir else 'h' |
914f0b99 | 154 | continue |
92d992d2 | 155 | edge = self.edge_type() |
16211e24 UH |
156 | if edge == 'e': |
157 | self.reset_decoder_state() # Reset state machine upon errors. | |
158 | continue | |
914f0b99 | 159 | if self.state == 'MID1': |
92d992d2 UH |
160 | self.state = 'START1' if edge == 's' else 'MID0' |
161 | bit = None if edge == 's' else 0 | |
914f0b99 | 162 | elif self.state == 'MID0': |
92d992d2 UH |
163 | self.state = 'START0' if edge == 's' else 'MID1' |
164 | bit = None if edge == 's' else 1 | |
914f0b99 | 165 | elif self.state == 'START1': |
92d992d2 | 166 | if edge == 's': |
914f0b99 | 167 | self.state = 'MID1' |
92d992d2 | 168 | bit = 1 if edge == 's' else None |
914f0b99 | 169 | elif self.state == 'START0': |
92d992d2 | 170 | if edge == 's': |
914f0b99 | 171 | self.state = 'MID0' |
92d992d2 | 172 | bit = 0 if edge == 's' else None |
914f0b99 UH |
173 | |
174 | self.edges.append(self.samplenum) | |
35b380b1 | 175 | if bit is not None: |
914f0b99 UH |
176 | self.bits.append([self.samplenum, bit]) |
177 | ||
cbbccbf4 | 178 | if len(self.bits) == 14: |
914f0b99 | 179 | self.handle_bits() |
16211e24 | 180 | self.reset_decoder_state() |
914f0b99 | 181 | |
681bad2a | 182 | self.next_edge = 'l' if self.ir else 'h' |