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.'
36 {'id': 'data', 'name': 'Data', 'desc': 'Data line'},
39 {'id': 'coilfreq', 'desc': 'Coil frequency', 'default': 125000},
40 {'id': 'start_gap', 'desc': 'Start gap min', 'default': 20},
41 {'id': 'w_gap', 'desc': 'Write gap min', 'default': 20},
42 {'id': 'w_one_min', 'desc': 'Write one min', 'default': 48},
43 {'id': 'w_one_max', 'desc': 'Write one max', 'default': 63},
44 {'id': 'w_zero_min', 'desc': 'Write zero min', 'default': 16},
45 {'id': 'w_zero_max', 'desc': 'Write zero max', 'default': 31},
46 {'id': 'em4100_decode', 'desc': 'EM4100 decode', 'default': 'on',
47 'values': ('on', 'off')},
50 ('bit_value', 'Bit value'),
51 ('start_gap', 'Start gap'),
52 ('write_gap', 'Write gap'),
53 ('write_mode_exit', 'Write mode exit'),
58 ('password', 'Password'),
59 ('address', 'Address'),
60 ('bitrate', 'Bitrate'),
63 ('bits', 'Bits', (0,)),
64 ('structure', 'Structure', (1, 2, 3, 4)),
65 ('fields', 'Fields', (5, 6, 7, 8, 9)),
66 ('decode', 'Decode', (10,)),
73 self.samplerate = None
74 self.last_samplenum = None
75 self.lastlast_samplenum = None
76 self.state = 'START_GAP'
77 self.bits_pos = [[0 for col in range(3)] for row in range(70)]
78 self.br_string = ['RF/8', 'RF/16', 'RF/32', 'RF/40',
79 'RF/50', 'RF/64', 'RF/100', 'RF/128']
80 self.mod_str1 = ['Direct', 'Manchester', 'Biphase', 'Reserved']
81 self.mod_str2 = ['Direct', 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2',
83 self.pskcf_str = ['RF/2', 'RF/4', 'RF/8', 'Reserved']
84 self.em4100_decode1_partial = 0
86 def metadata(self, key, value):
87 if key == srd.SRD_CONF_SAMPLERATE:
88 self.samplerate = value
89 self.field_clock = self.samplerate / self.options['coilfreq']
90 self.wzmax = self.options['w_zero_max'] * self.field_clock
91 self.wzmin = self.options['w_zero_min'] * self.field_clock
92 self.womax = self.options['w_one_max'] * self.field_clock
93 self.womin = self.options['w_one_min'] * self.field_clock
94 self.startgap = self.options['start_gap'] * self.field_clock
95 self.writegap = self.options['w_gap'] * self.field_clock
96 self.nogap = 64 * self.field_clock
99 self.out_ann = self.register(srd.OUTPUT_ANN)
101 def decode_config(self, idx):
102 safer_key = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
103 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
104 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
105 [10, ['Safer Key' + ': %X' % safer_key,'%X' % safer_key]])
106 bitrate = self.bits_pos[idx+11][0]<<2 | self.bits_pos[idx+12][0]<<1 | \
107 self.bits_pos[idx+13][0]
108 self.put(self.bits_pos[idx+11][1], self.bits_pos[idx+13][2],
109 self.out_ann, [10, ['Data Bit Rate: ' + \
110 self.br_string[bitrate], self.br_string[bitrate]]])
111 modulation1 = self.bits_pos[idx+15][0]<<1 | self.bits_pos[idx+16][0]
112 modulation2 = self.bits_pos[idx+17][0]<<2 | \
113 self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]
115 mod_string = self.mod_str2[modulation2]
117 mod_string = self.mod_str1[modulation1]
118 self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2],
119 self.out_ann, [10, ['Modulation: ' + mod_string, mod_string]])
120 psk_cf = self.bits_pos[idx+20][0]<<1 | self.bits_pos[idx+21][0]
121 self.put(self.bits_pos[idx+20][1], self.bits_pos[idx+21][2],
122 self.out_ann, [10, ['PSK-CF: ' + self.pskcf_str[psk_cf],
123 self.pskcf_str[psk_cf]]])
124 self.put(self.bits_pos[idx+22][1], self.bits_pos[idx+22][2],
125 self.out_ann, [10, ['AOR' + ': %d' % \
126 (self.bits_pos[idx+22][0]),'%d' % (self.bits_pos[idx+22][0])]])
127 maxblock = self.bits_pos[idx+24][0]<<2 | self.bits_pos[idx+25][0]<<1 | \
128 self.bits_pos[idx+26][0]
129 self.put(self.bits_pos[idx+24][1], self.bits_pos[idx+26][2],
130 self.out_ann, [10, ['Max-Block' + ': %d' % maxblock,
132 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+27][2],
133 self.out_ann, [10, ['PWD' + ': %d' % \
134 (self.bits_pos[idx+27][0]),'%d' % (self.bits_pos[idx+27][0])]])
135 self.put(self.bits_pos[idx+28][1], self.bits_pos[idx+28][2],
136 self.out_ann, [10, ['ST-sequence terminator' + ': %d' % \
137 (self.bits_pos[idx+28][0]),'%d' % (self.bits_pos[idx+28][0])]])
138 self.put(self.bits_pos[idx+31][1], self.bits_pos[idx+31][2],
139 self.out_ann, [10, ['POR delay' + ': %d' % \
140 (self.bits_pos[idx+31][0]),'%d' % (self.bits_pos[idx+31][0])]])
142 def put4bits(self, idx):
143 bits = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
144 self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
145 self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
148 def em4100_decode1(self, idx):
149 self.put(self.bits_pos[idx][1], self.bits_pos[idx+8][2], self.out_ann,
150 [10, ['EM4100 header', 'EM header', 'Header', 'H']])
152 self.put4bits(idx+14)
153 self.put4bits(idx+19)
154 self.put4bits(idx+24)
155 self.em4100_decode1_partial = self.bits_pos[idx+29][0]<<3 | \
156 self.bits_pos[idx+30][0]<<2 | self.bits_pos[idx+31][0]<<1
157 self.put(self.bits_pos[idx+29][1], self.bits_pos[idx+31][2],
158 self.out_ann, [10, ['Partial nibble']])
160 def em4100_decode2(self, idx):
161 if self.em4100_decode1_partial != 0:
162 bits = self.em4100_decode1_partial + self.bits_pos[idx][0]
163 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
164 self.out_ann, [10, ['%X' % bits]])
165 self.em4100_decode1_partial = 0
167 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
168 self.out_ann, [10, ['Partial nibble']])
172 self.put4bits(idx+12)
173 self.put4bits(idx+17)
174 self.put4bits(idx+22)
175 self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+31][2],
176 self.out_ann, [10, ['EM4100 trailer']])
178 def get_32_bits(self, idx):
180 for i in range(0, 32):
182 retval |= self.bits_pos[i+idx][0]
185 def get_3_bits(self, idx):
186 retval = self.bits_pos[idx][0]<<2 | self.bits_pos[idx+1][0]<<1 | \
187 self.bits_pos[idx+2][0]
190 def put_fields(self):
191 if (self.bit_nr == 70):
192 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
193 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
194 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
195 self.bits_pos[1][0])]])
196 password = self.get_32_bits(2)
197 self.put(self.bits_pos[2][1], self.bits_pos[33][2], self.out_ann,
198 [8, ['Password' + ': %X' % password, '%X' % password]])
199 self.put(self.bits_pos[34][1], self.bits_pos[34][2], self.out_ann,
200 [6, ['Lock' + ': %X' % self.bits_pos[34][0],
201 '%X' % self.bits_pos[34][0]]])
202 data = self.get_32_bits(35)
203 self.put(self.bits_pos[35][1], self.bits_pos[66][2], self.out_ann,
204 [7, ['Data' + ': %X' % data, '%X' % data]])
205 addr = self.get_3_bits(67)
206 self.put(self.bits_pos[67][1], self.bits_pos[69][2], self.out_ann,
207 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
209 self.decode_config(35)
211 self.put(self.bits_pos[35][1], self.bits_pos[66][2],
212 self.out_ann, [10, ['Password' + ': %X' % data,
214 # If we are programming EM4100 data we can decode it halfway.
215 if addr == 1 and self.options['em4100_decode'] == 'on':
216 self.em4100_decode1(35)
217 if addr == 2 and self.options['em4100_decode'] == 'on':
218 self.em4100_decode2(35)
220 if (self.bit_nr == 38):
221 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
222 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
223 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
224 self.bits_pos[1][0])]])
225 self.put(self.bits_pos[2][1], self.bits_pos[2][2], self.out_ann,
226 [6, ['Lock' + ': %X' % self.bits_pos[2][0],
227 '%X' % self.bits_pos[2][0]]])
228 data = self.get_32_bits(3)
229 self.put(self.bits_pos[3][1], self.bits_pos[34][2], self.out_ann,
230 [7, ['Data' + ': %X' % data, '%X' % data]])
231 addr = self.get_3_bits(35)
232 self.put(self.bits_pos[35][1], self.bits_pos[37][2], self.out_ann,
233 [9, ['Addr' + ': %X' % addr, '%X' % addr]])
235 self.decode_config(3)
237 self.put(self.bits_pos[3][1], self.bits_pos[34][2],
238 self.out_ann, [10, ['Password' + ': %X' % data,
240 # If we are programming EM4100 data we can decode it halfway.
241 if addr == 1 and self.options['em4100_decode'] == 'on':
242 self.em4100_decode1(3)
243 if addr == 2 and self.options['em4100_decode'] == 'on':
244 self.em4100_decode2(3)
246 if (self.bit_nr == 2):
247 self.put(self.bits_pos[0][1], self.bits_pos[1][2], self.out_ann,
248 [5, ['Opcode' + ': %d%d' % (self.bits_pos[0][0],
249 self.bits_pos[1][0]), '%d%d' % (self.bits_pos[0][0],
250 self.bits_pos[1][0])]])
253 def add_bits_pos(self, bit, bit_start, bit_end):
255 self.bits_pos[self.bit_nr][0] = bit
256 self.bits_pos[self.bit_nr][1] = bit_start
257 self.bits_pos[self.bit_nr][2] = bit_end
261 if not self.samplerate:
262 raise SamplerateError('Cannot decode without samplerate.')
264 self.last_samplenum = 0
265 self.lastlast_samplenum = 0
269 self.oldsamplenum = 0
270 self.last_bit_pos = 0
271 self.old_gap_start = 0
273 self.gap_detected = 0
277 (pin,) = self.wait({0: 'e'})
279 pl = self.samplenum - self.oldsamplenum
281 samples = self.samplenum - self.last_samplenum
283 if self.state == 'WRITE_GAP':
284 if pl > self.writegap:
285 self.gap_detected = 1
286 self.put(self.last_samplenum, self.samplenum,
287 self.out_ann, [2, ['Write gap']])
288 if (self.last_samplenum-self.old_gap_end) > self.nogap:
289 self.gap_detected = 0
290 self.state = 'START_GAP'
291 self.put(self.old_gap_end, self.last_samplenum,
292 self.out_ann, [3, ['Write mode exit']])
295 if self.state == 'START_GAP':
296 if pl > self.startgap:
297 self.gap_detected = 1
298 self.put(self.last_samplenum, self.samplenum,
299 self.out_ann, [1, ['Start gap']])
300 self.state = 'WRITE_GAP'
302 if self.gap_detected == 1:
303 self.gap_detected = 0
304 if (self.last_samplenum - self.old_gap_end) > self.wzmin \
305 and (self.last_samplenum - self.old_gap_end) < self.wzmax:
306 self.put(self.old_gap_end, self.last_samplenum,
307 self.out_ann, [0, ['0']])
308 self.put(self.old_gap_end, self.last_samplenum,
309 self.out_ann, [4, ['Bit']])
310 self.add_bits_pos(0, self.old_gap_end,
312 if (self.last_samplenum - self.old_gap_end) > self.womin \
313 and (self.last_samplenum - self.old_gap_end) < self.womax:
314 self.put(self.old_gap_end, self.last_samplenum,
315 self.out_ann, [0, ['1']])
316 self.put(self.old_gap_end, self.last_samplenum,
317 self.out_ann, [4, ['Bit']])
318 self.add_bits_pos(1, self.old_gap_end, self.last_samplenum)
320 self.old_gap_start = self.last_samplenum
321 self.old_gap_end = self.samplenum
325 self.oldsamplenum = self.samplenum
326 self.last_samplenum = self.samplenum