]>
Commit | Line | Data |
---|---|---|
2a2c9b16 | 1 | ## |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2018 Steve R <steversig@virginmedia.com> | |
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 | |
17 | ## along with this program; if not, see <http://www.gnu.org/licenses/>. | |
18 | ## | |
19 | ||
20 | import sigrokdecode as srd | |
21 | ||
3f55b14c UH |
22 | bitvals = ('0', '1', 'f', 'U') |
23 | ||
02aa01ad SA |
24 | def decode_bit(edges, pulses_per_bit): |
25 | if pulses_per_bit == 2: | |
26 | # Datasheet says long pulse is 3 times short pulse. | |
27 | lmin = 1.5 # long min multiplier | |
28 | lmax = 5 # long max multiplier | |
29 | if (edges[1] >= edges[0] * lmin and edges[1] <= edges[0] * lmax): # 0 -___ | |
30 | return '0' | |
31 | elif (edges[0] >= edges[1] * lmin and edges[0] <= edges[1] * lmax): # 1 ---_ | |
32 | return '1' | |
33 | # No float type for this line encoding | |
34 | else: | |
35 | return 'U' | |
36 | ||
37 | if pulses_per_bit == 4: | |
38 | # Datasheet says long pulse is 3 times short pulse. | |
39 | lmin = 2 # long min multiplier | |
40 | lmax = 5 # long max multiplier | |
41 | eqmin = 0.5 # equal min multiplier | |
42 | eqmax = 1.5 # equal max multiplier | |
43 | if ( # 0 -___-___ | |
44 | (edges[1] >= edges[0] * lmin and edges[1] <= edges[0] * lmax) and | |
45 | (edges[2] >= edges[0] * eqmin and edges[2] <= edges[0] * eqmax) and | |
46 | (edges[3] >= edges[0] * lmin and edges[3] <= edges[0] * lmax)): | |
47 | return '0' | |
48 | elif ( # 1 ---_---_ | |
49 | (edges[0] >= edges[1] * lmin and edges[0] <= edges[1] * lmax) and | |
50 | (edges[0] >= edges[2] * eqmin and edges[0] <= edges[2] * eqmax) and | |
51 | (edges[0] >= edges[3] * lmin and edges[0] <= edges[3] * lmax)): | |
52 | return '1' | |
53 | elif ( # float ---_-___ | |
54 | (edges[1] >= edges[0] * lmin and edges[1] <= edges[0] * lmax) and | |
55 | (edges[2] >= edges[0] * lmin and edges[2] <= edges[0]* lmax) and | |
56 | (edges[3] >= edges[0] * eqmin and edges[3] <= edges[0] * eqmax)): | |
57 | return 'f' | |
58 | else: | |
59 | return 'U' | |
60 | ||
61 | def pinlabels(bit_count, packet_bit_count): | |
62 | if packet_bit_count == 12: | |
63 | if bit_count <= 6: | |
64 | return 'A%i' % (bit_count - 1) | |
65 | else: | |
66 | return 'A%i/D%i' % (bit_count - 1, 12 - bit_count) | |
67 | ||
68 | if packet_bit_count == 24: | |
69 | if bit_count <= 20: | |
70 | return 'A%i' % (bit_count - 1) | |
71 | else: | |
72 | return 'D%i' % (bit_count - 21) | |
2a2c9b16 | 73 | |
74 | def decode_model(model, bits): | |
75 | if model == 'maplin_l95ar': | |
02aa01ad | 76 | address = 'Addr' # Address bits A0 to A5 |
2a2c9b16 | 77 | for i in range(0, 6): |
e7b18ee3 | 78 | address += ' %i:' % (i + 1) + ('on' if bits[i][0] == '0' else 'off') |
2a2c9b16 | 79 | button = 'Button' |
02aa01ad | 80 | # Button bits A6/D5 to A11/D0 |
2a2c9b16 | 81 | if bits[6][0] == '0' and bits[11][0] == '0': |
e7b18ee3 | 82 | button += ' A ON/OFF' |
2a2c9b16 | 83 | elif bits[7][0] == '0' and bits[11][0] == '0': |
e7b18ee3 | 84 | button += ' B ON/OFF' |
2a2c9b16 | 85 | elif bits[9][0] == '0' and bits[11][0] == '0': |
e7b18ee3 | 86 | button += ' C ON/OFF' |
2a2c9b16 | 87 | elif bits[8][0] == '0' and bits[11][0] == '0': |
e7b18ee3 | 88 | button += ' D ON/OFF' |
2a2c9b16 | 89 | else: |
e7b18ee3 | 90 | button += ' Unknown' |
02aa01ad SA |
91 | return [address, bits[0][1], bits[5][2], \ |
92 | button, bits[6][1], bits[11][2]] | |
93 | ||
94 | if model == 'xx1527': | |
95 | addr = 0 | |
96 | addr_valid = 1 | |
97 | for i in range(0, 20): | |
98 | if bits[i][0] != 'U': | |
99 | addr += int(bits[i][0]) * 2 ** i | |
100 | else: | |
101 | addr_valid = 0 | |
102 | ||
103 | if addr_valid == 1: | |
104 | address = 'Address 0x%X %X %X' % (addr & 0xFF, (addr >> 8) & 0xFF, addr >> 16) | |
105 | else: | |
106 | address = 'Invalid address as not all bits are 0 or 1' | |
107 | ||
108 | output = ' K0 = ' + bits[20][0] + ',' | |
109 | output += ' K1 = ' + bits[21][0] + ',' | |
110 | output += ' K2 = ' + bits[22][0] + ',' | |
111 | output += ' K3 = ' + bits[23][0] | |
112 | return [address, bits[0][1], bits[19][2], \ | |
113 | output, bits[20][1], bits[23][2]] | |
2a2c9b16 | 114 | |
115 | class Decoder(srd.Decoder): | |
116 | api_version = 3 | |
117 | id = 'rc_encode' | |
118 | name = 'RC encode' | |
119 | longname = 'Remote control encoder' | |
02aa01ad | 120 | desc = 'PT22x2/HX22x2/SC52x2 and xx1527 remote control encoder protocol.' |
2a2c9b16 | 121 | license = 'gplv2+' |
122 | inputs = ['logic'] | |
123 | outputs = [] | |
d6d8a8a4 | 124 | tags = ['IC', 'IR'] |
2a2c9b16 | 125 | channels = ( |
126 | {'id': 'data', 'name': 'Data', 'desc': 'Data line'}, | |
127 | ) | |
128 | annotations = ( | |
3f55b14c UH |
129 | ('bit-0', 'Bit 0'), |
130 | ('bit-1', 'Bit 1'), | |
131 | ('bit-f', 'Bit f'), | |
132 | ('bit-U', 'Bit U'), | |
133 | ('bit-sync', 'Bit sync'), | |
134 | ('pin', 'Pin'), | |
d46b71ed UH |
135 | ('code-word-addr', 'Code word address'), |
136 | ('code-word-data', 'Code word data'), | |
2a2c9b16 | 137 | ) |
138 | annotation_rows = ( | |
3f55b14c UH |
139 | ('bits', 'Bits', (0, 1, 2, 3, 4)), |
140 | ('pins', 'Pins', (5,)), | |
d46b71ed | 141 | ('code-words', 'Code words', (6, 7)), |
2a2c9b16 | 142 | ) |
143 | options = ( | |
02aa01ad SA |
144 | {'id': 'linecoding', 'desc': 'Encoding', 'default': 'SC52x2/HX22x2', 'values': ('SC52x2/HX22x2', 'xx1527')}, |
145 | {'id': 'remote', 'desc': 'Remote', 'default': 'none', 'values': ('none', 'maplin_l95ar')}, | |
2a2c9b16 | 146 | ) |
147 | ||
148 | def __init__(self): | |
149 | self.reset() | |
150 | ||
151 | def reset(self): | |
152 | self.samplenumber_last = None | |
153 | self.pulses = [] | |
154 | self.bits = [] | |
155 | self.labels = [] | |
156 | self.bit_count = 0 | |
218b5139 UH |
157 | self.ss = None |
158 | self.es = None | |
2a2c9b16 | 159 | self.state = 'IDLE' |
160 | ||
161 | def start(self): | |
162 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
163 | self.model = self.options['remote'] | |
02aa01ad SA |
164 | if self.options['linecoding'] == 'xx1527': |
165 | self.pulses_per_bit = 2 | |
166 | self.packet_bits = 24 | |
167 | self.model = 'xx1527' | |
168 | else: | |
169 | self.pulses_per_bit = 4 # Each bit is repeated | |
170 | self.packet_bits = 12 | |
2a2c9b16 | 171 | |
3a843174 UH |
172 | def putx(self, data): |
173 | self.put(self.ss, self.es, self.out_ann, data) | |
174 | ||
2a2c9b16 | 175 | def decode(self): |
176 | while True: | |
177 | pin = self.wait({0: 'e'}) | |
178 | self.state = 'DECODING' | |
179 | ||
180 | if not self.samplenumber_last: # Set counters to start of signal. | |
181 | self.samplenumber_last = self.samplenum | |
218b5139 | 182 | self.ss = self.samplenum |
2a2c9b16 | 183 | continue |
184 | ||
02aa01ad | 185 | if self.bit_count < self.packet_bits: # Decode A0 to A11 / A23. |
2a2c9b16 | 186 | self.bit_count += 1 |
02aa01ad | 187 | for i in range(0, self.pulses_per_bit): |
2a2c9b16 | 188 | if i > 0: |
02aa01ad | 189 | pin = self.wait({0: 'e'}) # Get next edges if we need more. |
2a2c9b16 | 190 | samples = self.samplenum - self.samplenumber_last |
191 | self.pulses.append(samples) # Save the pulse width. | |
192 | self.samplenumber_last = self.samplenum | |
218b5139 | 193 | self.es = self.samplenum |
02aa01ad | 194 | self.bits.append([decode_bit(self.pulses, self.pulses_per_bit), self.ss, |
218b5139 | 195 | self.es]) # Save states and times. |
02aa01ad SA |
196 | idx = bitvals.index(decode_bit(self.pulses, self.pulses_per_bit)) |
197 | self.putx([idx, [decode_bit(self.pulses, self.pulses_per_bit)]]) # Write decoded bit. | |
198 | self.putx([5, [pinlabels(self.bit_count, self.packet_bits)]]) # Write pin labels. | |
2a2c9b16 | 199 | self.pulses = [] |
218b5139 | 200 | self.ss = self.samplenum |
2a2c9b16 | 201 | else: |
202 | if self.model != 'none': | |
203 | self.labels = decode_model(self.model, self.bits) | |
204 | self.put(self.labels[1], self.labels[2], self.out_ann, | |
3f55b14c | 205 | [6, [self.labels[0]]]) # Write model decode. |
2a2c9b16 | 206 | self.put(self.labels[4], self.labels[5], self.out_ann, |
d46b71ed | 207 | [7, [self.labels[3]]]) # Write model decode. |
2a2c9b16 | 208 | samples = self.samplenum - self.samplenumber_last |
209 | pin = self.wait({'skip': 8 * samples}) # Wait for end of sync bit. | |
218b5139 | 210 | self.es = self.samplenum |
3f55b14c | 211 | self.putx([4, ['Sync']]) # Write sync label. |
2a2c9b16 | 212 | self.reset() # Reset and wait for next set of pulses. |
213 | self.state = 'DECODE_TIMEOUT' | |
214 | if not self.state == 'DECODE_TIMEOUT': | |
215 | self.samplenumber_last = self.samplenum |