2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2015 Benjamin Larsson <benjamin@southpole.se>
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.
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.
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/>.
20 import sigrokdecode as srd
22 class SamplerateError(Exception):
25 class Decoder(srd.Decoder):
29 longname = 'RFID T55xx'
30 desc = 'T55xx 100-150kHz RFID protocol.'
35 {'id': 'data', 'name': 'Data', 'desc': 'Data line'},
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')},
49 ('bit_value', 'Bit value'),
50 ('start_gap', 'Start gap'),
51 ('write_gap', 'Write gap'),
52 ('write_mode_exit', 'Write mode exit'),
57 ('password', 'Password'),
58 ('address', 'Address'),
59 ('bitrate', 'Bitrate'),
62 ('bits', 'Bits', (0,)),
63 ('structure', 'Structure', (1, 2, 3, 4)),
64 ('fields', 'Fields', (5, 6, 7, 8, 9)),
65 ('decode', 'Decode', (10,)),
69 self.samplerate = None
70 self.last_samplenum = None
71 self.lastlast_samplenum = None
72 self.state = 'START_GAP'
73 self.bits_pos = [[0 for col in range(3)] for row in range(70)]
74 self.br_string = ['RF/8', 'RF/16', 'RF/32', 'RF/40',
75 'RF/50', 'RF/64', 'RF/100', 'RF/128']
76 self.mod_str1 = ['Direct', 'Manchester', 'Biphase', 'Reserved']
77 self.mod_str2 = ['Direct', 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2',
79 self.pskcf_str = ['RF/2', 'RF/4', 'RF/8', 'Reserved']
80 self.em4100_decode1_partial = 0
82 def metadata(self, key, value):
83 if key == srd.SRD_CONF_SAMPLERATE:
84 self.samplerate = value
85 self.field_clock = self.samplerate / self.options['coilfreq']
86 self.wzmax = self.options['w_zero_max'] * self.field_clock
87 self.wzmin = self.options['w_zero_min'] * self.field_clock
88 self.womax = self.options['w_one_max'] * self.field_clock
89 self.womin = self.options['w_one_min'] * self.field_clock
90 self.startgap = self.options['start_gap'] * self.field_clock
91 self.writegap = self.options['w_gap'] * self.field_clock
92 self.nogap = 64 * self.field_clock
95 self.out_ann = self.register(srd.OUTPUT_ANN)
97 def decode_config(self, idx):
98 safer_key = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
99 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
100 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
101 [10, ['Safer Key' + ': %X' % safer_key,'%X' % safer_key]])
102 bitrate = self.bits_pos[idx+11][0]<<2 | self.bits_pos[idx+12][0]<<1 | \
103 self.bits_pos[idx+13][0]
104 self.put(self.bits_pos[idx+11][1], self.bits_pos[idx+13][2],
105 self.out_ann, [10, ['Data Bit Rate: ' + \
106 self.br_string[bitrate], self.br_string[bitrate]]])
107 modulation1 = self.bits_pos[idx+15][0]<<1 | self.bits_pos[idx+16][0]
108 modulation2 = self.bits_pos[idx+17][0]<<2 | \
109 self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]
111 mod_string = self.mod_str2[modulation2]
113 mod_string = self.mod_str1[modulation1]
114 self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2],
115 self.out_ann, [10, ['Modulation: ' + mod_string, mod_string]])
116 psk_cf = self.bits_pos[idx+20][0]<<1 | self.bits_pos[idx+21][0]
117 self.put(self.bits_pos[idx+20][1], self.bits_pos[idx+21][2],
118 self.out_ann, [10, ['PSK-CF: ' + self.pskcf_str[psk_cf],
119 self.pskcf_str[psk_cf]]])
120 self.put(self.bits_pos[idx+22][1], self.bits_pos[idx+22][2],
121 self.out_ann, [10, ['AOR' + ': %d' % \
122 (self.bits_pos[idx+22][0]),'%d' % (self.bits_pos[idx+22][0])]])
123 maxblock = self.bits_pos[idx+24][0]<<2 | self.bits_pos[idx+25][0]<<1 | \
124 self.bits_pos[idx+26][0]
125 self.put(self.bits_pos[idx+24][1], self.bits_pos[idx+26][2],
126 self.out_ann, [10, ['Max-Block' + ': %d' % maxblock,
128 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+27][2],
129 self.out_ann, [10, ['PWD' + ': %d' % \
130 (self.bits_pos[idx+27][0]),'%d' % (self.bits_pos[idx+27][0])]])
131 self.put(self.bits_pos[idx+28][1], self.bits_pos[idx+28][2],
132 self.out_ann, [10, ['ST-sequence terminator' + ': %d' % \
133 (self.bits_pos[idx+28][0]),'%d' % (self.bits_pos[idx+28][0])]])
134 self.put(self.bits_pos[idx+31][1], self.bits_pos[idx+31][2],
135 self.out_ann, [10, ['POR delay' + ': %d' % \
136 (self.bits_pos[idx+31][0]),'%d' % (self.bits_pos[idx+31][0])]])
138 def put4bits(self, idx):
139 bits = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
140 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
141 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
144 def em4100_decode1(self, idx):
145 self.put(self.bits_pos[idx][1], self.bits_pos[idx+8][2], self.out_ann,
146 [10, ['EM4100 header', 'EM header', 'Header', 'H']])
148 self.put4bits(idx+14)
149 self.put4bits(idx+19)
150 self.put4bits(idx+24)
151 self.em4100_decode1_partial = self.bits_pos[idx+29][0]<<3 | \
152 self.bits_pos[idx+30][0]<<2 | self.bits_pos[idx+31][0]<<1
153 self.put(self.bits_pos[idx+29][1], self.bits_pos[idx+31][2],
154 self.out_ann, [10, ['Partial nibble']])
156 def em4100_decode2(self, idx):
157 if self.em4100_decode1_partial != 0:
158 bits = self.em4100_decode1_partial + self.bits_pos[idx][0]
159 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
160 self.out_ann, [10, ['%X' % bits]])
161 self.em4100_decode1_partial = 0
163 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
164 self.out_ann, [10, ['Partial nibble']])
168 self.put4bits(idx+12)
169 self.put4bits(idx+17)
170 self.put4bits(idx+22)
171 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+31][2],
172 self.out_ann, [10, ['EM4100 trailer']])
174 def get_32_bits(self, idx):
176 for i in range(0, 32):
178 retval |= self.bits_pos[i+idx][0]
181 def get_3_bits(self, idx):
182 retval = self.bits_pos[idx][0]<<2 | self.bits_pos[idx+1][0]<<1 | \
183 self.bits_pos[idx+2][0]
186 def put_fields(self):
187 if (self.bit_nr == 70):
188 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
189 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
190 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
191 self.bits_pos[1][0])]])
192 password = self.get_32_bits(2)
193 self.put(self.bits_pos[2][1], self.bits_pos[33][2], self.out_ann,
194 [8, ['Password' + ': %X' % password, '%X' % password]])
195 self.put(self.bits_pos[34][1], self.bits_pos[34][2], self.out_ann,
196 [6, ['Lock' + ': %X' % self.bits_pos[34][0],
197 '%X' % self.bits_pos[34][0]]])
198 data = self.get_32_bits(35)
199 self.put(self.bits_pos[35][1], self.bits_pos[66][2], self.out_ann,
200 [7, ['Data' + ': %X' % data, '%X' % data]])
201 addr = self.get_3_bits(67)
202 self.put(self.bits_pos[67][1], self.bits_pos[69][2], self.out_ann,
203 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
205 self.decode_config(35)
207 self.put(self.bits_pos[35][1], self.bits_pos[66][2],
208 self.out_ann, [10, ['Password' + ': %X' % data,
210 # If we are programming EM4100 data we can decode it halfway.
211 if addr == 1 and self.options['em4100_decode'] == 'on':
212 self.em4100_decode1(35)
213 if addr == 2 and self.options['em4100_decode'] == 'on':
214 self.em4100_decode2(35)
216 if (self.bit_nr == 38):
217 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
218 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
219 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
220 self.bits_pos[1][0])]])
221 self.put(self.bits_pos[2][1], self.bits_pos[2][2], self.out_ann,
222 [6, ['Lock' + ': %X' % self.bits_pos[2][0],
223 '%X' % self.bits_pos[2][0]]])
224 data = self.get_32_bits(3)
225 self.put(self.bits_pos[3][1], self.bits_pos[34][2], self.out_ann,
226 [7, ['Data' + ': %X' % data, '%X' % data]])
227 addr = self.get_3_bits(35)
228 self.put(self.bits_pos[35][1], self.bits_pos[37][2], self.out_ann,
229 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
231 self.decode_config(3)
233 self.put(self.bits_pos[3][1], self.bits_pos[34][2],
234 self.out_ann, [10, ['Password' + ': %X' % data,
236 # If we are programming EM4100 data we can decode it halfway.
237 if addr == 1 and self.options['em4100_decode'] == 'on':
238 self.em4100_decode1(3)
239 if addr == 2 and self.options['em4100_decode'] == 'on':
240 self.em4100_decode2(3)
242 if (self.bit_nr == 2):
243 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
244 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
245 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
246 self.bits_pos[1][0])]])
249 def add_bits_pos(self, bit, bit_start, bit_end):
251 self.bits_pos[self.bit_nr][0] = bit
252 self.bits_pos[self.bit_nr][1] = bit_start
253 self.bits_pos[self.bit_nr][2] = bit_end
257 if not self.samplerate:
258 raise SamplerateError('Cannot decode without samplerate.')
260 self.last_samplenum = 0
261 self.lastlast_samplenum = 0
265 self.oldsamplenum = 0
266 self.last_bit_pos = 0
267 self.old_gap_start = 0
269 self.gap_detected = 0
273 (pin,) = self.wait({0: 'e'})
275 pl = self.samplenum - self.oldsamplenum
277 samples = self.samplenum - self.last_samplenum
279 if self.state == 'WRITE_GAP':
280 if pl > self.writegap:
281 self.gap_detected = 1
282 self.put(self.last_samplenum, self.samplenum,
283 self.out_ann, [2, ['Write gap']])
284 if (self.last_samplenum-self.old_gap_end) > self.nogap:
285 self.gap_detected = 0
286 self.state = 'START_GAP'
287 self.put(self.old_gap_end, self.last_samplenum,
288 self.out_ann, [3, ['Write mode exit']])
291 if self.state == 'START_GAP':
292 if pl > self.startgap:
293 self.gap_detected = 1
294 self.put(self.last_samplenum, self.samplenum,
295 self.out_ann, [1, ['Start gap']])
296 self.state = 'WRITE_GAP'
298 if self.gap_detected == 1:
299 self.gap_detected = 0
300 if (self.last_samplenum - self.old_gap_end) > self.wzmin \
301 and (self.last_samplenum - self.old_gap_end) < self.wzmax:
302 self.put(self.old_gap_end, self.last_samplenum,
303 self.out_ann, [0, ['0']])
304 self.put(self.old_gap_end, self.last_samplenum,
305 self.out_ann, [4, ['Bit']])
306 self.add_bits_pos(0, self.old_gap_end,
308 if (self.last_samplenum - self.old_gap_end) > self.womin \
309 and (self.last_samplenum - self.old_gap_end) < self.womax:
310 self.put(self.old_gap_end, self.last_samplenum,
311 self.out_ann, [0, ['1']])
312 self.put(self.old_gap_end, self.last_samplenum,
313 self.out_ann, [4, ['Bit']])
314 self.add_bits_pos(1, self.old_gap_end, self.last_samplenum)
316 self.old_gap_start = self.last_samplenum
317 self.old_gap_end = self.samplenum
321 self.oldsamplenum = self.samplenum
322 self.last_samplenum = self.samplenum