@@ -148,22 +148,13 @@ class BusyError(Exception):
148
148
"""Base class for exceptions in this module."""
149
149
pass
150
150
151
- class PN532_I2C(object):
152
- """PN532 breakout board representation. Requires a SPI connection to the
153
- breakout board. A software SPI connection is recommended as the hardware
154
- SPI on the Raspberry Pi has some issues with the LSB first mode used by the
155
- PN532 (see: http://www.raspberrypi.org/forums/viewtopic.php?f=32&t=98070&p=720659#p720659)
156
- """
151
+ class PN532:
152
+ """PN532 driver base, must be extended for I2C/SPI/UART interfacing"""
157
153
158
- def __init__(self, i2c, *, irq=None, reset=None, debug=False):
159
- """Create an instance of the PN532 class using either software SPI (if
160
- the sclk, mosi, and miso pins are specified) or hardware SPI if a
161
- spi parameter is passed. The cs pin must be a digital GPIO pin.
162
- Optionally specify a GPIO controller to override the default that uses
163
- the board's GPIO pins.
154
+ def __init__(self, *, debug=False, reset=None):
155
+ """Create an instance of the PN532 class
164
156
"""
165
157
self.debug = debug
166
- self._irq = irq
167
158
if reset:
168
159
print("resetting")
169
160
reset.direction = Direction.OUTPUT
@@ -173,14 +164,29 @@ def __init__(self, i2c, *, irq=None, reset=None, debug=False):
173
164
time.sleep(0.1)
174
165
reset.value = True
175
166
time.sleep(1)
176
- self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
177
167
try:
178
168
self.get_firmware_version() # first time often fails, try 2ce
179
169
return
180
170
except:
181
171
pass
182
172
self.get_firmware_version()
183
-
173
+
174
+ def _read_data(self, count):
175
+ # Read raw data from device, not including status bytes:
176
+ # Subclasses MUST implement this!
177
+ raise NotImplementedError
178
+
179
+ def _write_data(self, framebytes):
180
+ # Write raw bytestring data to device, not including status bytes:
181
+ # Subclasses MUST implement this!
182
+ raise NotImplementedError
183
+
184
+ def _wait_ready(self, timeout):
185
+ # Check if busy up to max length of 'timeout' seconds
186
+ # Subclasses MUST implement this!
187
+ raise NotImplementedError
188
+
189
+
184
190
def _write_frame(self, data):
185
191
"""Write a frame to the PN532 with the specified data bytearray."""
186
192
assert data is not None and 0 < len(data) < 255, 'Data must be array of 1 to 255 bytes.'
@@ -207,21 +213,7 @@ def _write_frame(self, data):
207
213
# Send frame.
208
214
if self.debug:
209
215
print('Write frame: ', [hex(i) for i in frame])
210
- with self._i2c:
211
- self._i2c.write(bytes(frame))
212
-
213
- def _read_data(self, count):
214
- """Read a specified count of bytes from the PN532."""
215
- # Build a read request frame.
216
- frame = bytearray(count+1)
217
- with self._i2c:
218
- self._i2c.readinto(frame, end=1) # read ready byte!
219
- if frame[0] != 0x01: # not ready
220
- raise BusyError
221
- self._i2c.readinto(frame)
222
- if self.debug:
223
- print("Reading: ", [hex(i) for i in frame[1:]])
224
- return frame[1:]
216
+ self._write_data(bytes(frame))
225
217
226
218
def _read_frame(self, length):
227
219
"""Read a response frame from the PN532 of at most length bytes in size.
@@ -255,21 +247,6 @@ def _read_frame(self, length):
255
247
# Return frame data.
256
248
return response[offset+2:offset+2+frame_len]
257
249
258
- def _wait_ready(self, timeout=1):
259
- if self._irq:
260
- print("TODO IRQ")
261
- else:
262
- status = bytearray(1)
263
- t = time.monotonic()
264
- while (time.monotonic() - t) < timeout:
265
- with self._i2c:
266
- self._i2c.readinto(status)
267
- if status == b'\x01':
268
- return True
269
- else:
270
- time.sleep(0.1)
271
- return True
272
-
273
250
def call_function(self, command, response_length=0, params=[], timeout=1):
274
251
"""Send specified command to the PN532 and expect up to response_length
275
252
bytes back in a response. Note that less than the expected bytes might
@@ -400,4 +377,52 @@ def mifare_classic_write_block(self, block_number, data):
400
377
response = self.call_function(_COMMAND_INDATAEXCHANGE,
401
378
params=params,
402
379
response_length=1)
403
- return response[0] == 0x00
380
+ return response[0] == 0x0
381
+
382
+
383
+
384
+ class PN532_I2C(PN532):
385
+ """Driver for the PN532 connected over I2C."""
386
+ def __init__(self, i2c, *, irq=None, reset=None, debug=False):
387
+ """Create an instance of the PN532 class using either software SPI (if
388
+ the sclk, mosi, and miso pins are specified) or hardware SPI if a
389
+ spi parameter is passed. The cs pin must be a digital GPIO pin.
390
+ Optionally specify a GPIO controller to override the default that uses
391
+ the board's GPIO pins.
392
+ """
393
+ self.debug = debug
394
+ self._irq = irq
395
+ self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
396
+ super().__init__(debug=debug, reset=reset)
397
+
398
+ def _wait_ready(self, timeout=1):
399
+ if self._irq:
400
+ print("TODO IRQ")
401
+ else:
402
+ status = bytearray(1)
403
+ t = time.monotonic()
404
+ while (time.monotonic() - t) < timeout:
405
+ with self._i2c:
406
+ self._i2c.readinto(status)
407
+ if status == b'\x01':
408
+ return True
409
+ else:
410
+ time.sleep(0.1)
411
+ return True
412
+
413
+ def _read_data(self, count):
414
+ """Read a specified count of bytes from the PN532."""
415
+ # Build a read request frame.
416
+ frame = bytearray(count+1)
417
+ with self._i2c:
418
+ self._i2c.readinto(frame, end=1) # read ready byte!
419
+ if frame[0] != 0x01: # not ready
420
+ raise BusyError
421
+ self._i2c.readinto(frame)
422
+ if self.debug:
423
+ print("Reading: ", [hex(i) for i in frame[1:]])
424
+ return frame[1:]
425
+
426
+ def _write_data(self, framebytes):
427
+ with self._i2c:
428
+ self._i2c.write(framebytes)
0 commit comments