]> sigrok.org Git - libsigrokdecode.git/blame - decoders/t55xx/pd.py
Make srd_inst_decode() return the actual decoder state, not SRD_OK
[libsigrokdecode.git] / decoders / t55xx / pd.py
CommitLineData
e2bc7a1e
BL
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2015 Benjamin Larsson <benjamin@southpole.se>
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
88df2c9a
UH
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
e2bc7a1e
BL
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/>.
e2bc7a1e
BL
18##
19
20import sigrokdecode as srd
21
22class SamplerateError(Exception):
23 pass
24
25class Decoder(srd.Decoder):
c551f324 26 api_version = 3
e2bc7a1e
BL
27 id = 't55xx'
28 name = 'T55xx'
29 longname = 'RFID T55xx'
30 desc = 'T55xx 100-150kHz RFID protocol.'
31 license = 'gplv2+'
32 inputs = ['logic']
33 outputs = ['t55xx']
34 channels = (
35 {'id': 'data', 'name': 'Data', 'desc': 'Data line'},
36 )
37 options = (
38 {'id': 'coilfreq', 'desc': 'Coil frequency', 'default': 125000},
39 {'id': 'start_gap', 'desc': 'Start gap min', 'default': 20},
40 {'id': 'w_gap', 'desc': 'Write gap min', 'default': 20},
41 {'id': 'w_one_min', 'desc': 'Write one min', 'default': 48},
42 {'id': 'w_one_max', 'desc': 'Write one max', 'default': 63},
43 {'id': 'w_zero_min', 'desc': 'Write zero min', 'default': 16},
44 {'id': 'w_zero_max', 'desc': 'Write zero max', 'default': 31},
45 {'id': 'em4100_decode', 'desc': 'EM4100 decode', 'default': 'on',
46 'values': ('on', 'off')},
47 )
48 annotations = (
49 ('bit_value', 'Bit value'),
50 ('start_gap', 'Start gap'),
51 ('write_gap', 'Write gap'),
52 ('write_mode_exit', 'Write mode exit'),
53 ('bit', 'Bit'),
54 ('opcode', 'Opcode'),
55 ('lock', 'Lock'),
56 ('data', 'Data'),
57 ('password', 'Password'),
58 ('address', 'Address'),
59 ('bitrate', 'Bitrate'),
60 )
61 annotation_rows = (
62 ('bits', 'Bits', (0,)),
63 ('structure', 'Structure', (1, 2, 3, 4)),
64 ('fields', 'Fields', (5, 6, 7, 8, 9)),
65 ('decode', 'Decode', (10,)),
66 )
67
92b7b49f 68 def __init__(self):
10aeb8ea
GS
69 self.reset()
70
71 def reset(self):
e2bc7a1e 72 self.samplerate = None
e2bc7a1e
BL
73 self.last_samplenum = None
74 self.lastlast_samplenum = None
75 self.state = 'START_GAP'
76 self.bits_pos = [[0 for col in range(3)] for row in range(70)]
77 self.br_string = ['RF/8', 'RF/16', 'RF/32', 'RF/40',
78 'RF/50', 'RF/64', 'RF/100', 'RF/128']
79 self.mod_str1 = ['Direct', 'Manchester', 'Biphase', 'Reserved']
80 self.mod_str2 = ['Direct', 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2',
81 'FSK1a', 'FSK2a']
82 self.pskcf_str = ['RF/2', 'RF/4', 'RF/8', 'Reserved']
83 self.em4100_decode1_partial = 0
84
85 def metadata(self, key, value):
86 if key == srd.SRD_CONF_SAMPLERATE:
87 self.samplerate = value
88 self.field_clock = self.samplerate / self.options['coilfreq']
89 self.wzmax = self.options['w_zero_max'] * self.field_clock
90 self.wzmin = self.options['w_zero_min'] * self.field_clock
91 self.womax = self.options['w_one_max'] * self.field_clock
92 self.womin = self.options['w_one_min'] * self.field_clock
93 self.startgap = self.options['start_gap'] * self.field_clock
94 self.writegap = self.options['w_gap'] * self.field_clock
95 self.nogap = 64 * self.field_clock
96
97 def start(self):
98 self.out_ann = self.register(srd.OUTPUT_ANN)
99
100 def decode_config(self, idx):
101 safer_key = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
102 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
103 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
104 [10, ['Safer Key' + ': %X' % safer_key,'%X' % safer_key]])
105 bitrate = self.bits_pos[idx+11][0]<<2 | self.bits_pos[idx+12][0]<<1 | \
106 self.bits_pos[idx+13][0]
107 self.put(self.bits_pos[idx+11][1], self.bits_pos[idx+13][2],
108 self.out_ann, [10, ['Data Bit Rate: ' + \
109 self.br_string[bitrate], self.br_string[bitrate]]])
110 modulation1 = self.bits_pos[idx+15][0]<<1 | self.bits_pos[idx+16][0]
111 modulation2 = self.bits_pos[idx+17][0]<<2 | \
112 self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]
113 if modulation1 == 0:
114 mod_string = self.mod_str2[modulation2]
115 else:
116 mod_string = self.mod_str1[modulation1]
117 self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2],
118 self.out_ann, [10, ['Modulation: ' + mod_string, mod_string]])
119 psk_cf = self.bits_pos[idx+20][0]<<1 | self.bits_pos[idx+21][0]
120 self.put(self.bits_pos[idx+20][1], self.bits_pos[idx+21][2],
121 self.out_ann, [10, ['PSK-CF: ' + self.pskcf_str[psk_cf],
122 self.pskcf_str[psk_cf]]])
123 self.put(self.bits_pos[idx+22][1], self.bits_pos[idx+22][2],
124 self.out_ann, [10, ['AOR' + ': %d' % \
125 (self.bits_pos[idx+22][0]),'%d' % (self.bits_pos[idx+22][0])]])
126 maxblock = self.bits_pos[idx+24][0]<<2 | self.bits_pos[idx+25][0]<<1 | \
127 self.bits_pos[idx+26][0]
128 self.put(self.bits_pos[idx+24][1], self.bits_pos[idx+26][2],
129 self.out_ann, [10, ['Max-Block' + ': %d' % maxblock,
130 '%d' % maxblock]])
131 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+27][2],
132 self.out_ann, [10, ['PWD' + ': %d' % \
133 (self.bits_pos[idx+27][0]),'%d' % (self.bits_pos[idx+27][0])]])
134 self.put(self.bits_pos[idx+28][1], self.bits_pos[idx+28][2],
135 self.out_ann, [10, ['ST-sequence terminator' + ': %d' % \
136 (self.bits_pos[idx+28][0]),'%d' % (self.bits_pos[idx+28][0])]])
137 self.put(self.bits_pos[idx+31][1], self.bits_pos[idx+31][2],
138 self.out_ann, [10, ['POR delay' + ': %d' % \
139 (self.bits_pos[idx+31][0]),'%d' % (self.bits_pos[idx+31][0])]])
140
141 def put4bits(self, idx):
142 bits = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
143 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
144 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
145 [10, ['%X' % bits]])
146
147 def em4100_decode1(self, idx):
148 self.put(self.bits_pos[idx][1], self.bits_pos[idx+8][2], self.out_ann,
149 [10, ['EM4100 header', 'EM header', 'Header', 'H']])
150 self.put4bits(idx+9)
151 self.put4bits(idx+14)
152 self.put4bits(idx+19)
153 self.put4bits(idx+24)
154 self.em4100_decode1_partial = self.bits_pos[idx+29][0]<<3 | \
155 self.bits_pos[idx+30][0]<<2 | self.bits_pos[idx+31][0]<<1
156 self.put(self.bits_pos[idx+29][1], self.bits_pos[idx+31][2],
157 self.out_ann, [10, ['Partial nibble']])
158
159 def em4100_decode2(self, idx):
160 if self.em4100_decode1_partial != 0:
161 bits = self.em4100_decode1_partial + self.bits_pos[idx][0]
162 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
163 self.out_ann, [10, ['%X' % bits]])
164 self.em4100_decode1_partial = 0
165 else:
166 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
167 self.out_ann, [10, ['Partial nibble']])
168
169 self.put4bits(idx+2)
170 self.put4bits(idx+7)
171 self.put4bits(idx+12)
172 self.put4bits(idx+17)
173 self.put4bits(idx+22)
174 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+31][2],
175 self.out_ann, [10, ['EM4100 trailer']])
176
177 def get_32_bits(self, idx):
178 retval = 0
179 for i in range(0, 32):
180 retval <<= 1
181 retval |= self.bits_pos[i+idx][0]
182 return retval
183
184 def get_3_bits(self, idx):
185 retval = self.bits_pos[idx][0]<<2 | self.bits_pos[idx+1][0]<<1 | \
186 self.bits_pos[idx+2][0]
187 return retval
188
189 def put_fields(self):
190 if (self.bit_nr == 70):
191 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
192 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
193 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
194 self.bits_pos[1][0])]])
195 password = self.get_32_bits(2)
196 self.put(self.bits_pos[2][1], self.bits_pos[33][2], self.out_ann,
197 [8, ['Password' + ': %X' % password, '%X' % password]])
198 self.put(self.bits_pos[34][1], self.bits_pos[34][2], self.out_ann,
199 [6, ['Lock' + ': %X' % self.bits_pos[34][0],
200 '%X' % self.bits_pos[34][0]]])
201 data = self.get_32_bits(35)
202 self.put(self.bits_pos[35][1], self.bits_pos[66][2], self.out_ann,
203 [7, ['Data' + ': %X' % data, '%X' % data]])
204 addr = self.get_3_bits(67)
205 self.put(self.bits_pos[67][1], self.bits_pos[69][2], self.out_ann,
206 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
207 if addr == 0:
208 self.decode_config(35)
209 if addr == 7:
210 self.put(self.bits_pos[35][1], self.bits_pos[66][2],
211 self.out_ann, [10, ['Password' + ': %X' % data,
212 '%X' % data]])
213 # If we are programming EM4100 data we can decode it halfway.
214 if addr == 1 and self.options['em4100_decode'] == 'on':
215 self.em4100_decode1(35)
216 if addr == 2 and self.options['em4100_decode'] == 'on':
217 self.em4100_decode2(35)
218
219 if (self.bit_nr == 38):
220 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
221 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
222 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
223 self.bits_pos[1][0])]])
224 self.put(self.bits_pos[2][1], self.bits_pos[2][2], self.out_ann,
225 [6, ['Lock' + ': %X' % self.bits_pos[2][0],
226 '%X' % self.bits_pos[2][0]]])
227 data = self.get_32_bits(3)
228 self.put(self.bits_pos[3][1], self.bits_pos[34][2], self.out_ann,
229 [7, ['Data' + ': %X' % data, '%X' % data]])
230 addr = self.get_3_bits(35)
231 self.put(self.bits_pos[35][1], self.bits_pos[37][2], self.out_ann,
232 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
233 if addr == 0:
234 self.decode_config(3)
235 if addr == 7:
236 self.put(self.bits_pos[3][1], self.bits_pos[34][2],
237 self.out_ann, [10, ['Password' + ': %X' % data,
238 '%X' % data]])
239 # If we are programming EM4100 data we can decode it halfway.
240 if addr == 1 and self.options['em4100_decode'] == 'on':
241 self.em4100_decode1(3)
242 if addr == 2 and self.options['em4100_decode'] == 'on':
243 self.em4100_decode2(3)
244
245 if (self.bit_nr == 2):
246 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
247 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
248 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
249 self.bits_pos[1][0])]])
250 self.bit_nr = 0
251
252 def add_bits_pos(self, bit, bit_start, bit_end):
253 if self.bit_nr < 70:
254 self.bits_pos[self.bit_nr][0] = bit
255 self.bits_pos[self.bit_nr][1] = bit_start
256 self.bits_pos[self.bit_nr][2] = bit_end
257 self.bit_nr += 1
258
c551f324 259 def decode(self):
e2bc7a1e
BL
260 if not self.samplerate:
261 raise SamplerateError('Cannot decode without samplerate.')
e2bc7a1e 262
c551f324
GS
263 self.last_samplenum = 0
264 self.lastlast_samplenum = 0
265 self.last_edge = 0
266 self.oldpl = 0
267 self.oldpp = 0
268 self.oldsamplenum = 0
269 self.last_bit_pos = 0
270 self.old_gap_start = 0
271 self.old_gap_end = 0
272 self.gap_detected = 0
273 self.bit_nr = 0
e2bc7a1e 274
c551f324
GS
275 while True:
276 (pin,) = self.wait({0: 'e'})
e2bc7a1e 277
c551f324
GS
278 pl = self.samplenum - self.oldsamplenum
279 pp = pin
280 samples = self.samplenum - self.last_samplenum
e2bc7a1e 281
c551f324
GS
282 if self.state == 'WRITE_GAP':
283 if pl > self.writegap:
284 self.gap_detected = 1
285 self.put(self.last_samplenum, self.samplenum,
286 self.out_ann, [2, ['Write gap']])
287 if (self.last_samplenum-self.old_gap_end) > self.nogap:
288 self.gap_detected = 0
289 self.state = 'START_GAP'
290 self.put(self.old_gap_end, self.last_samplenum,
291 self.out_ann, [3, ['Write mode exit']])
292 self.put_fields()
e2bc7a1e 293
c551f324
GS
294 if self.state == 'START_GAP':
295 if pl > self.startgap:
296 self.gap_detected = 1
297 self.put(self.last_samplenum, self.samplenum,
298 self.out_ann, [1, ['Start gap']])
299 self.state = 'WRITE_GAP'
e2bc7a1e 300
c551f324
GS
301 if self.gap_detected == 1:
302 self.gap_detected = 0
303 if (self.last_samplenum - self.old_gap_end) > self.wzmin \
304 and (self.last_samplenum - self.old_gap_end) < self.wzmax:
305 self.put(self.old_gap_end, self.last_samplenum,
306 self.out_ann, [0, ['0']])
307 self.put(self.old_gap_end, self.last_samplenum,
308 self.out_ann, [4, ['Bit']])
309 self.add_bits_pos(0, self.old_gap_end,
310 self.last_samplenum)
311 if (self.last_samplenum - self.old_gap_end) > self.womin \
312 and (self.last_samplenum - self.old_gap_end) < self.womax:
313 self.put(self.old_gap_end, self.last_samplenum,
314 self.out_ann, [0, ['1']])
315 self.put(self.old_gap_end, self.last_samplenum,
316 self.out_ann, [4, ['Bit']])
317 self.add_bits_pos(1, self.old_gap_end, self.last_samplenum)
e2bc7a1e 318
c551f324
GS
319 self.old_gap_start = self.last_samplenum
320 self.old_gap_end = self.samplenum
e2bc7a1e 321
c551f324
GS
322 self.oldpl = pl
323 self.oldpp = pp
324 self.oldsamplenum = self.samplenum
325 self.last_samplenum = self.samplenum