mfrc522 1.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/iso144434.rb DELETED
@@ -1,245 +0,0 @@
1
- class ISO144434 < PICC
2
- FSCI_to_FSC = [16, 24, 32, 40, 48, 64, 96, 128, 256]
3
-
4
- CMD_RATS = 0xE0
5
- CMD_PPS = 0xD0
6
- CMD_DESELECT = 0xC2
7
- CMD_SUCCESS = 0x00
8
- CMD_ADDITIONAL_FRAME = 0xAF
9
-
10
- def initialize(pcd, uid, sak)
11
- super
12
-
13
- @cid = 0x00 # We don't support CID
14
- @fsc = 16 # Assume PICC only supports 16 bytes frame
15
- @fwt = 256 # 77.33ms(256 ticks) default frame waiting time
16
-
17
- @support_cid = false
18
- @support_nad = false
19
- @block_number = 0
20
- @selected = false
21
- end
22
-
23
- # ISO/IEC 14443-4 select
24
- def select
25
- # Send RATS (Request for Answer To Select)
26
- buffer = [CMD_RATS, 0x50 | @cid]
27
- received_data = @pcd.picc_transceive(buffer)
28
-
29
- dr, ds = process_ats(received_data)
30
-
31
- # Send PPS (Protocol and Parameter Selection Request)
32
- buffer = [CMD_PPS | @cid, 0x11, (ds << 2) | dr]
33
- received_data = @pcd.picc_transceive(buffer)
34
- raise UnexpectedDataError, 'Incorrect response' if received_data[0] != (0xD0 | @cid)
35
-
36
- # Set PCD baud rate
37
- @pcd.transceiver_baud_rate(:tx, dr)
38
- @pcd.transceiver_baud_rate(:rx, ds)
39
-
40
- @block_number = 0
41
- @max_frame_size = [64, @fsc].min
42
- @max_inf_size = @max_frame_size - 3 # PCB + CRC16
43
- @max_inf_size -= 1 if @support_cid
44
- @max_inf_size -= 1 if @support_nad
45
- @selected = true
46
- end
47
-
48
- # Send S(DESELECT)
49
- def deselect
50
- buffer = [CMD_DESELECT]
51
- received_data = @pcd.picc_transceive(buffer)
52
-
53
- if received_data[0] & 0xF7 == CMD_DESELECT
54
- @selected = false
55
- true
56
- else
57
- false
58
- end
59
- end
60
-
61
- # Wrapper for handling ISO protocol
62
- def transceive(send_data)
63
- # Split data according to max buffer size
64
- send_data = [send_data] unless send_data.is_a? Array
65
- chained_data = send_data.each_slice(@max_inf_size).to_a
66
-
67
- # Initialize I-block
68
- pcb = 0x02
69
-
70
- # Send chained data
71
- until chained_data.empty?
72
- pcb &= 0xEF # Reset chaining indicator
73
- pcb |= 0x10 if chained_data.size > 1 # Set chaining
74
- pcb |= @block_number # Set block number
75
- data = chained_data.shift
76
-
77
- buffer = [pcb] + data
78
-
79
- finished = false
80
- until finished
81
- received_data = handle_wtx(buffer)
82
-
83
- # Retreive response pcb from data
84
- r_pcb = received_data[0]
85
-
86
- # Received ACK
87
- if r_pcb & 0xF6 == 0xA2
88
- # If ACK matches current block number means success
89
- # Otherwise transmit it again
90
- if (pcb & 0x01) == (r_pcb & 0x01)
91
- finished = true
92
- end
93
- else
94
- finished = true
95
- end
96
- end
97
-
98
- @block_number ^= 1 # toggle block number for next frame
99
- end
100
-
101
- received_chained_data = [received_data]
102
-
103
- # Receive chained data
104
- while r_pcb & 0x10 != 0
105
- ack = 0xA2 | @block_number # Set block number
106
- received_data = handle_wtx([ack]) # Send ACK to receive next frame
107
-
108
- r_pcb = received_data[0]
109
-
110
- received_chained_data << received_data
111
-
112
- @block_number ^= 1 # toggle block number for next frame
113
- end
114
-
115
- # Collect INF from chain
116
- inf = []
117
- received_chained_data.each do |data|
118
- inf_position = 1
119
- inf_position += 1 if data[0] & 0x08 != 0 # CID present
120
- inf_position += 1 if data[0] & 0x04 != 0 # NAD present
121
-
122
- inf.concat(data[inf_position..-1])
123
- end
124
-
125
- inf
126
- end
127
-
128
- def resume_communication
129
- deselect rescue nil
130
- super
131
- end
132
-
133
- def halt
134
- deselect rescue nil
135
- super
136
- end
137
-
138
- private
139
-
140
- def convert_iso_baud_rate_to_pcd_setting(value)
141
- # ISO
142
- # 0b000: 106kBd, 0b001: 212kBd, 0b010: 424kBd, 0b100: 848kBd
143
- # MFRC522 register
144
- # 0b000: 106kBd, 0b001: 212kBd, 0b010: 424kBd, 0b011: 848kBd
145
- x = (value >> 2) & 0x01
146
- y = (value >> 1) & 0x01
147
- z = value & 0x01
148
-
149
- ((x | y) << 1) + (x | (~y & z))
150
- end
151
-
152
- # Gether information from ATS (Answer to Select)
153
- def process_ats(ats)
154
- position = 1
155
- t0 = ats[position] # Format byte
156
-
157
- fsci = t0 & 0x0F # PICC buffer size integer
158
- y1 = (t0 >> 4) & 0x07 # Optional frame(TA, TB, TC) indicator
159
- @fsc = FSCI_to_FSC.fetch(fsci) # Convert buffer size integer to bytes
160
- dr = 0 # default baud rate 106kBd
161
- ds = 0
162
-
163
- # Frame: TA
164
- if y1 & 0x01 != 0
165
- position += 1
166
- ta = ats[position]
167
-
168
- dr = ta & 0x07 # PCD to PICC baud rate
169
- ds = (ta >> 4) & 0x07 # PICC to PCD baud rate
170
-
171
- # Convert fastest baud rate to PCD setting
172
- dr = convert_iso_baud_rate_to_pcd_setting(dr)
173
- ds = convert_iso_baud_rate_to_pcd_setting(ds)
174
-
175
- dr = 0
176
- ds = 0
177
- end
178
-
179
- # Frame: TB
180
- if y1 & 0x02 != 0
181
- position += 1
182
- tb = ats[position]
183
-
184
- fwi = (tb >> 4) & 0x0F # Frame wating integer
185
- sgfi = tb & 0x0F # Start-up frame guard integer
186
-
187
- # Convert integers to real time
188
- @fwt = (1 << fwi)
189
- sgft = (1 << sgfi)
190
-
191
- # Set frame waiting time
192
- @pcd.internal_timer(@fwt)
193
- end
194
-
195
- # Get info about CID or NAD
196
- if y1 & 0x04 != 0
197
- position += 1
198
- tc = ats[position]
199
-
200
- @support_cid = true if tc & 0x02 != 0
201
- @support_nad = true if tc & 0x01 != 0
202
- end
203
-
204
- # Start-up guard time
205
- sleep 0.000302 * sgft
206
-
207
- return dr, ds
208
- end
209
-
210
- def handle_wtx(data)
211
- 24.times do
212
- begin
213
- received_data = @pcd.picc_transceive(data)
214
- rescue CommunicationError => e
215
- raise e unless e.is_a? PICCTimeoutError
216
-
217
- # Try sending NAK when timeout
218
- nak = 0xB2 | @block_number
219
- data = [nak]
220
- next
221
- end
222
-
223
- pcb = received_data[0]
224
-
225
- # WTX detected
226
- if pcb & 0xF7 == 0xF2
227
- inf_position = (pcb & 0x08 != 0) ? 2 : 1
228
- wtxm = received_data[inf_position] & 0x3F
229
-
230
- # Set temporary timer
231
- @pcd.internal_timer(@fwt * wtxm)
232
-
233
- # Set WTX response
234
- data = [0xF2, wtxm]
235
- else
236
- # Set timer back to FWT
237
- @pcd.internal_timer(@fwt)
238
-
239
- return received_data
240
- end
241
- end
242
-
243
- raise PICCTimeoutError
244
- end
245
- end