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 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 20import sigrokdecode as srd 21 22class SamplerateError(Exception): 23 pass 24 25class Decoder(srd.Decoder): 26 api_version = 3 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 = [] 34 tags = ['IC', 'RFID'] 35 channels = ( 36 {'id': 'data', 'name': 'Data', 'desc': 'Data line'}, 37 ) 38 options = ( 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')}, 48 ) 49 annotations = ( 50 ('bit_value', 'Bit value'), 51 ('start_gap', 'Start gap'), 52 ('write_gap', 'Write gap'), 53 ('write_mode_exit', 'Write mode exit'), 54 ('bit', 'Bit'), 55 ('opcode', 'Opcode'), 56 ('lock', 'Lock'), 57 ('data', 'Data'), 58 ('password', 'Password'), 59 ('address', 'Address'), 60 ('bitrate', 'Bitrate'), 61 ) 62 annotation_rows = ( 63 ('bits', 'Bits', (0,)), 64 ('structure', 'Structure', (1, 2, 3, 4)), 65 ('fields', 'Fields', (5, 6, 7, 8, 9)), 66 ('decode', 'Decode', (10,)), 67 ) 68 69 def __init__(self): 70 self.reset() 71 72 def reset(self): 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', 82 'FSK1a', 'FSK2a'] 83 self.pskcf_str = ['RF/2', 'RF/4', 'RF/8', 'Reserved'] 84 self.em4100_decode1_partial = 0 85 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 97 98 def start(self): 99 self.out_ann = self.register(srd.OUTPUT_ANN) 100 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] 114 if modulation1 == 0: 115 mod_string = self.mod_str2[modulation2] 116 else: 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, 131 '%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])]]) 141 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, 146 [10, ['%X' % bits]]) 147 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']]) 151 self.put4bits(idx+9) 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']]) 159 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 166 else: 167 self.put(self.bits_pos[idx][1], self.bits_pos[idx][2], 168 self.out_ann, [10, ['Partial nibble']]) 169 170 self.put4bits(idx+2) 171 self.put4bits(idx+7) 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']]) 177 178 def get_32_bits(self, idx): 179 retval = 0 180 for i in range(0, 32): 181 retval <<= 1 182 retval |= self.bits_pos[i+idx][0] 183 return retval 184 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] 188 return retval 189 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]]) 208 if addr == 0: 209 self.decode_config(35) 210 if addr == 7: 211 self.put(self.bits_pos[35][1], self.bits_pos[66][2], 212 self.out_ann, [10, ['Password' + ': %X' % data, 213 '%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) 219 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]]) 234 if addr == 0: 235 self.decode_config(3) 236 if addr == 7: 237 self.put(self.bits_pos[3][1], self.bits_pos[34][2], 238 self.out_ann, [10, ['Password' + ': %X' % data, 239 '%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) 245 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])]]) 251 self.bit_nr = 0 252 253 def add_bits_pos(self, bit, bit_start, bit_end): 254 if self.bit_nr < 70: 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 258 self.bit_nr += 1 259 260 def decode(self): 261 if not self.samplerate: 262 raise SamplerateError('Cannot decode without samplerate.') 263 264 self.last_samplenum = 0 265 self.lastlast_samplenum = 0 266 self.last_edge = 0 267 self.oldpl = 0 268 self.oldpp = 0 269 self.oldsamplenum = 0 270 self.last_bit_pos = 0 271 self.old_gap_start = 0 272 self.old_gap_end = 0 273 self.gap_detected = 0 274 self.bit_nr = 0 275 276 while True: 277 (pin,) = self.wait({0: 'e'}) 278 279 pl = self.samplenum - self.oldsamplenum 280 pp = pin 281 samples = self.samplenum - self.last_samplenum 282 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']]) 293 self.put_fields() 294 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' 301 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, 311 self.last_samplenum) 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) 319 320 self.old_gap_start = self.last_samplenum 321 self.old_gap_end = self.samplenum 322 323 self.oldpl = pl 324 self.oldpp = pp 325 self.oldsamplenum = self.samplenum 326 self.last_samplenum = self.samplenum 327