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