Skip to content

Commit f1f0b7a

Browse files
committed
pulled i2c into its own subclass
1 parent aa36758 commit f1f0b7a

File tree

1 file changed

+71
-46
lines changed

1 file changed

+71
-46
lines changed

adafruit_pn532.py

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -148,22 +148,13 @@ class BusyError(Exception):
148148
"""Base class for exceptions in this module."""
149149
pass
150150

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"""
157153

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
164156
"""
165157
self.debug = debug
166-
self._irq = irq
167158
if reset:
168159
print("resetting")
169160
reset.direction = Direction.OUTPUT
@@ -173,14 +164,29 @@ def __init__(self, i2c, *, irq=None, reset=None, debug=False):
173164
time.sleep(0.1)
174165
reset.value = True
175166
time.sleep(1)
176-
self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
177167
try:
178168
self.get_firmware_version() # first time often fails, try 2ce
179169
return
180170
except:
181171
pass
182172
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+
184190
def _write_frame(self, data):
185191
"""Write a frame to the PN532 with the specified data bytearray."""
186192
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):
207213
# Send frame.
208214
if self.debug:
209215
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))
225217

226218
def _read_frame(self, length):
227219
"""Read a response frame from the PN532 of at most length bytes in size.
@@ -255,21 +247,6 @@ def _read_frame(self, length):
255247
# Return frame data.
256248
return response[offset+2:offset+2+frame_len]
257249

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-
273250
def call_function(self, command, response_length=0, params=[], timeout=1):
274251
"""Send specified command to the PN532 and expect up to response_length
275252
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):
400377
response = self.call_function(_COMMAND_INDATAEXCHANGE,
401378
params=params,
402379
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

Comments
 (0)