]> sigrok.org Git - libsigrokdecode.git/blame - decoders/em4100/pd.py
Add RFID EM4100 protocol decoding
[libsigrokdecode.git] / decoders / em4100 / pd.py
CommitLineData
8f265907
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
8## the Free Software Foundation; either data 2 of the License, or
9## (at your option) any later data.
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, write to the Free Software
18## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19##
20
21import sigrokdecode as srd
22
23class SamplerateError(Exception):
24 pass
25
26class Decoder(srd.Decoder):
27 api_version = 2
28 id = 'em4100'
29 name = 'EM4100'
30 longname = 'RFID EM4100'
31 desc = 'EM4100 100-150kHz RFID protocol.'
32 license = 'gplv2+'
33 inputs = ['logic']
34 outputs = ['em4100']
35 channels = (
36 {'id': 'data', 'name': 'Data', 'desc': 'Data line'},
37 )
38 options = (
39 {'id': 'polarity', 'desc': 'Polarity', 'default': 'active-high',
40 'values': ('active-low', 'active-high')},
41 {'id': 'datarate' , 'desc': 'Data rate', 'default': '64',
42 'values': ('64', '32', '16')},
43# {'id': 'coding', 'desc': 'Bit coding', 'default': 'biphase',
44# 'values': ('biphase', 'manchester', 'psk')},
45 {'id': 'coilfreq', 'desc': 'Coil frequency', 'default': '125000'},
46 )
47 annotations = (
48 ('headerbit', 'Header bit'),
49 ('databit', 'Version bit'),
50 ('rowparity', 'Row Parity'),
51 ('databit', 'Data bit'),
52 ('colparity', 'Column Parity'),
53 ('stopbit', 'Stop bit'),
54 ('rowparity_check', 'Row Parity Check'),
55 )
56 annotation_rows = (
57 ('bits', 'Bits', (0,)),
58 ('fields', 'Fields', (1, 2, 4, 7)),
59 ('value', 'Value', (3, 5, 6, 8)),
60 )
61
62 def __init__(self, **kwargs):
63 self.samplerate = None
64 self.oldpin = None
65 self.last_samplenum = None
66 self.lastlast_samplenum = None
67 self.last_edge = 0
68 self.bit_width = 0
69 self.halfbit_limit = 0
70 self.oldpp = 0
71 self.oldpl = 0
72 self.oldsamplenum = 0
73 self.last_bit_pos = 0
74 self.first_start = 0
75 self.first_one = 0
76 self.state = 'HEADER'
77 self.data = 0
78 self.data_bits = 0
79 self.data_start = 0
80 self.data_parity = 0
81 self.payload_cnt = 0
82 self.data_col_parity = [0, 0, 0, 0, 0, 0]
83 self.col_parity = [0, 0, 0, 0, 0, 0]
84
85 def metadata(self, key, value):
86 if key == srd.SRD_CONF_SAMPLERATE:
87 self.samplerate = value
88 self.bit_width = (self.samplerate / (int(self.options['coilfreq']))) * int(self.options['datarate'])
89 self.halfbit_limit = self.bit_width/2 + self.bit_width/4
90 self.polarity = 0 if self.options['polarity'] == 'active-low' else 1
91
92 def start(self):
93 self.out_ann = self.register(srd.OUTPUT_ANN)
94
95 def add_bit(self, bit, bit_start, bit_stop):
96 if self.state == 'HEADER':
97 if bit == 1:
98 if self.first_one > 0:
99 self.first_one += 1
100 if self.first_one == 9:
101 self.put(int(self.first_start), int(bit_stop), self.out_ann,
102 [1, ['Header', 'Head', 'He', 'H']])
103 self.first_one = 0
104 self.state = 'PAYLOAD'
105 return
106 if self.first_one == 0:
107 self.first_one = 1
108 self.first_start = bit_start
109
110 if bit == 0:
111 self.first_one = 0
112 return
113
114 if self.state == 'PAYLOAD':
115 self.payload_cnt += 1
116 if self.data_bits == 0:
117 self.data_start = bit_start
118 self.data = 0
119 self.data_parity = 0
120 self.data_bits += 1
121 if self.data_bits == 5:
122 self.put(int(self.data_start), int(bit_start), self.out_ann,
123 [2, ['Data', 'Da', 'D']])
124 self.put(int(bit_start), int(bit_stop), self.out_ann,
125 [4, ['Parity', 'Par', 'Pa', 'P']])
126 self.put(int(self.data_start), int(bit_start), self.out_ann,
127 [3, [str("%X" % self.data)]])
128 if self.data_parity == bit:
129 p_string = ['OK', 'O']
130 else:
131 p_string = ['ERROR', 'ERR', 'ER', 'E']
132 self.put(int(bit_start), int(bit_stop), self.out_ann,
133 [6, p_string])
134 self.data_bits = 0
135 if self.payload_cnt == 50:
136 self.state = 'TRAILER'
137 self.payload_cnt = 0
138
139 self.data_parity ^= bit
140 self.data_col_parity[self.data_bits] ^= bit
141 self.data = (self.data << 1) | bit
142 return
143
144 if self.state == 'TRAILER':
145 self.payload_cnt += 1
146 if self.data_bits == 0:
147 self.data_start = bit_start
148 self.data = 0
149 self.data_parity = 0
150 self.data_bits += 1
151 self.col_parity[self.data_bits] = bit
152
153 if self.data_bits == 5:
154 p_string = ['ERROR', 'ERR', 'ER', 'E']
155 if self.data_col_parity[1] == self.col_parity[1]:
156 if self.data_col_parity[2] == self.col_parity[2]:
157 if self.data_col_parity[3] == self.col_parity[3]:
158 if self.data_col_parity[4] == self.col_parity[4]:
159 p_string = ['OK', 'O']
160
161 self.put(int(self.data_start), int(bit_start), self.out_ann,
162 [4, ['Column parity', 'Col par', 'CP', 'P']])
163 self.put(int(bit_start), int(bit_stop), self.out_ann,
164 [4, ['Stop bit', 'St bi', 'SB', 'S']])
165 self.put(int(self.data_start), int(bit_start), self.out_ann,
166 [6, p_string])
167
168 self.data_bits = 0
169 if self.payload_cnt == 5:
170 self.state = 'HEADER'
171 self.payload_cnt = 0
172 self.data_col_parity = [0, 0, 0, 0, 0, 0]
173 self.col_parity = [0, 0, 0, 0, 0, 0]
174
175 def putbit(self, bit, bit_start, bit_stop):
176 self.put(int(bit_start), int(bit_stop), self.out_ann,
177 [0, [str(bit)]])
178 self.add_bit(bit, bit_start, bit_stop)
179
180 def manchester_decode(self, samplenum, pl, pp, pin):
181 bit_start = 0
182 bit_stop = 0
183 bit = self.oldpin ^ self.polarity
184 if pl > self.halfbit_limit:
185 samples = samplenum - self.oldsamplenum
186 t = samples / self.samplerate
187
188 if self.oldpl > self.halfbit_limit:
189 bit_start = int(self.oldsamplenum - self.oldpl/2)
190 bit_stop = int(samplenum - pl/2)
191 self.putbit(bit, bit_start, bit_stop)
192 if self.oldpl <= self.halfbit_limit:
193 bit_start = int(self.oldsamplenum - self.oldpl)
194 bit_stop = int(samplenum - pl/2)
195 self.putbit(bit, bit_start, bit_stop)
196 self.last_bit_pos = int(samplenum - pl/2)
197
198 if pl < self.halfbit_limit:
199 samples = samplenum - self.oldsamplenum
200 t = samples / self.samplerate
201
202 if self.oldpl > self.halfbit_limit:
203 bit_start = self.oldsamplenum - self.oldpl/2
204 bit_stop = int(samplenum)
205 self.putbit(bit, bit_start, bit_stop)
206 self.last_bit_pos = int(samplenum)
207 if self.oldpl <= self.halfbit_limit:
208 if self.last_bit_pos <= self.oldsamplenum - self.oldpl:
209 bit_start = self.oldsamplenum - self.oldpl
210 bit_stop = int(samplenum)
211 self.putbit(bit, bit_start, bit_stop)
212 self.last_bit_pos = int(samplenum)
213
214 def decode(self, ss, es, data):
215 if not self.samplerate:
216 raise SamplerateError('Cannot decode without samplerate.')
217 for (samplenum, (pin,)) in data:
218 # Ignore identical samples early on (for performance reasons).
219 if self.oldpin == pin:
220 continue
221
222 if self.oldpin is None:
223 self.oldpin = pin
224 self.last_samplenum = samplenum
225 self.lastlast_samplenum = samplenum
226 self.last_edge = samplenum
227 self.oldpl = 0
228 self.oldpp = 0
229 self.oldsamplenum = 0
230 self.last_bit_pos = 0
231 continue
232
233 if self.oldpin != pin:
234 pl = samplenum - self.oldsamplenum
235 pp = pin
236
237 self.manchester_decode(samplenum, pl, pp, pin)
238
239 self.oldpl = pl
240 self.oldpp = pp
241 self.oldsamplenum = samplenum
242 self.oldpin = pin