Skip to content

Commit 98c47df

Browse files
authored
Merge pull request #6 from caternuson/iss3_refactor
Refactoring to save memory
2 parents f558870 + 08fa1ea commit 98c47df

File tree

9 files changed

+344
-197
lines changed

9 files changed

+344
-197
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ install:
2525
- pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
2626
- pip install --force-reinstall pylint==1.9.2
2727
script:
28-
- pylint adafruit_pn532.py
28+
- pylint adafruit_pn532/*.py
2929
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace
3030
examples/*.py)
3131
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-pn532 --library_location .

adafruit_pn532/__init__.py

Whitespace-only changes.

adafruit_pn532.py renamed to adafruit_pn532/adafruit_pn532.py

Lines changed: 1 addition & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,8 @@
4646
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
4747
"""
4848

49-
5049
import time
5150
from digitalio import Direction
52-
import adafruit_bus_device.i2c_device as i2c_device
53-
import adafruit_bus_device.spi_device as spi_device
5451

5552
from micropython import const
5653

@@ -105,13 +102,6 @@
105102

106103
_WAKEUP = const(0x55)
107104

108-
_SPI_STATREAD = const(0x02)
109-
_SPI_DATAWRITE = const(0x01)
110-
_SPI_DATAREAD = const(0x03)
111-
_SPI_READY = const(0x01)
112-
113-
_I2C_ADDRESS = const(0x24)
114-
115105
_MIFARE_ISO14443A = const(0x00)
116106

117107
# Mifare Commands
@@ -186,22 +176,12 @@ def _reset(pin):
186176
pin.value = True
187177
time.sleep(0.1)
188178

189-
def reverse_bit(num):
190-
"""Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
191-
it is LSB for the PN532, but 99% of SPI implementations are MSB only!"""
192-
result = 0
193-
for _ in range(8):
194-
result <<= 1
195-
result += (num & 1)
196-
num >>= 1
197-
return result
198-
199-
200179

201180
class BusyError(Exception):
202181
"""Base class for exceptions in this module."""
203182
pass
204183

184+
205185
class PN532:
206186
"""PN532 driver base, must be extended for I2C/SPI/UART interfacing"""
207187

@@ -464,167 +444,3 @@ def ntag2xx_read_block(self, block_number):
464444
not read then None will be returned.
465445
"""
466446
return self.mifare_classic_read_block(block_number)[0:4] # only 4 bytes per page
467-
468-
class PN532_UART(PN532):
469-
"""Driver for the PN532 connected over Serial UART"""
470-
def __init__(self, uart, *, irq=None, reset=None, debug=False):
471-
"""Create an instance of the PN532 class using Serial connection.
472-
Optional IRQ pin (not used), reset pin and debugging output.
473-
"""
474-
self.debug = debug
475-
self._irq = irq
476-
self._uart = uart
477-
super().__init__(debug=debug, reset=reset)
478-
479-
def _wakeup(self):
480-
"""Send any special commands/data to wake up PN532"""
481-
#self._write_frame([_HOSTTOPN532, _COMMAND_SAMCONFIGURATION, 0x01])
482-
self.SAM_configuration()
483-
484-
def _wait_ready(self, timeout=1):
485-
"""Wait `timeout` seconds"""
486-
time.sleep(timeout)
487-
return True
488-
489-
def _read_data(self, count):
490-
"""Read a specified count of bytes from the PN532."""
491-
frame = self._uart.read(count)
492-
if not frame:
493-
raise BusyError("No data read from PN532")
494-
if self.debug:
495-
print("Reading: ", [hex(i) for i in frame])
496-
else:
497-
time.sleep(0.1)
498-
return frame
499-
500-
def _write_data(self, framebytes):
501-
"""Write a specified count of bytes to the PN532"""
502-
while self._uart.read(1): # this would be a lot nicer if we could query the # of bytes
503-
pass
504-
self._uart.write('\x55\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # wake up!
505-
self._uart.write(framebytes)
506-
507-
class PN532_I2C(PN532):
508-
"""Driver for the PN532 connected over I2C."""
509-
def __init__(self, i2c, *, irq=None, reset=None, req=None, debug=False):
510-
"""Create an instance of the PN532 class using I2C. Note that PN532
511-
uses clock stretching. Optional IRQ pin (not used),
512-
reset pin and debugging output.
513-
"""
514-
self.debug = debug
515-
self._irq = irq
516-
self._req = req
517-
if reset:
518-
_reset(reset)
519-
self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
520-
super().__init__(debug=debug, reset=reset)
521-
522-
def _wakeup(self): # pylint: disable=no-self-use
523-
"""Send any special commands/data to wake up PN532"""
524-
if self._req:
525-
self._req.direction = Direction.OUTPUT
526-
self._req.value = True
527-
time.sleep(0.1)
528-
self._req.value = False
529-
time.sleep(0.1)
530-
self._req.value = True
531-
time.sleep(0.5)
532-
533-
def _wait_ready(self, timeout=1):
534-
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
535-
status = bytearray(1)
536-
timestamp = time.monotonic()
537-
while (time.monotonic() - timestamp) < timeout:
538-
try:
539-
with self._i2c:
540-
self._i2c.readinto(status)
541-
except OSError:
542-
self._wakeup()
543-
continue
544-
if status == b'\x01':
545-
return True # No longer busy
546-
else:
547-
time.sleep(0.05) # lets ask again soon!
548-
# Timed out!
549-
return False
550-
551-
def _read_data(self, count):
552-
"""Read a specified count of bytes from the PN532."""
553-
# Build a read request frame.
554-
frame = bytearray(count+1)
555-
with self._i2c as i2c:
556-
i2c.readinto(frame, end=1) # read status byte!
557-
if frame[0] != 0x01: # not ready
558-
raise BusyError
559-
i2c.readinto(frame) # ok get the data, plus statusbyte
560-
if self.debug:
561-
print("Reading: ", [hex(i) for i in frame[1:]])
562-
else:
563-
time.sleep(0.1)
564-
return frame[1:] # don't return the status byte
565-
566-
def _write_data(self, framebytes):
567-
"""Write a specified count of bytes to the PN532"""
568-
with self._i2c as i2c:
569-
i2c.write(framebytes)
570-
571-
class PN532_SPI(PN532):
572-
"""Driver for the PN532 connected over SPI. Pass in a hardware or bitbang
573-
SPI device & chip select digitalInOut pin. Optional IRQ pin (not used),
574-
reset pin and debugging output."""
575-
def __init__(self, spi, cs_pin, *, irq=None, reset=None, debug=False):
576-
"""Create an instance of the PN532 class using SPI"""
577-
self.debug = debug
578-
self._irq = irq
579-
self._spi = spi_device.SPIDevice(spi, cs_pin)
580-
super().__init__(debug=debug, reset=reset)
581-
582-
def _wakeup(self):
583-
"""Send any special commands/data to wake up PN532"""
584-
with self._spi as spi:
585-
time.sleep(1)
586-
spi.write(bytearray([0x00])) #pylint: disable=no-member
587-
time.sleep(1)
588-
589-
def _wait_ready(self, timeout=1):
590-
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
591-
status = bytearray([reverse_bit(_SPI_STATREAD), 0])
592-
593-
timestamp = time.monotonic()
594-
while (time.monotonic() - timestamp) < timeout:
595-
with self._spi as spi:
596-
time.sleep(0.02) # required
597-
spi.write_readinto(status, status) #pylint: disable=no-member
598-
if reverse_bit(status[1]) == 0x01: # LSB data is read in MSB
599-
return True # Not busy anymore!
600-
else:
601-
time.sleep(0.01) # pause a bit till we ask again
602-
# We timed out!
603-
return False
604-
605-
def _read_data(self, count):
606-
"""Read a specified count of bytes from the PN532."""
607-
# Build a read request frame.
608-
frame = bytearray(count+1)
609-
# Add the SPI data read signal byte, but LSB'ify it
610-
frame[0] = reverse_bit(_SPI_DATAREAD)
611-
612-
with self._spi as spi:
613-
time.sleep(0.02) # required
614-
spi.write_readinto(frame, frame) #pylint: disable=no-member
615-
for i, val in enumerate(frame):
616-
frame[i] = reverse_bit(val) # turn LSB data to MSB
617-
if self.debug:
618-
print("Reading: ", [hex(i) for i in frame[1:]])
619-
return frame[1:]
620-
621-
def _write_data(self, framebytes):
622-
"""Write a specified count of bytes to the PN532"""
623-
# start by making a frame with data write in front,
624-
# then rest of bytes, and LSBify it
625-
rev_frame = [reverse_bit(x) for x in bytes([_SPI_DATAWRITE]) + framebytes]
626-
if self.debug:
627-
print("Writing: ", [hex(i) for i in rev_frame])
628-
with self._spi as spi:
629-
time.sleep(0.02) # required
630-
spi.write(bytes(rev_frame)) #pylint: disable=no-member

adafruit_pn532/i2c.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Adafruit PN532 NFC/RFID control library.
2+
# Author: Tony DiCola
3+
#
4+
# The MIT License (MIT)
5+
#
6+
# Copyright (c) 2015-2018 Adafruit Industries
7+
#
8+
# Permission is hereby granted, free of charge, to any person obtaining a copy
9+
# of this software and associated documentation files (the "Software"), to deal
10+
# in the Software without restriction, including without limitation the rights
11+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
# copies of the Software, and to permit persons to whom the Software is
13+
# furnished to do so, subject to the following conditions:
14+
#
15+
# The above copyright notice and this permission notice shall be included in
16+
# all copies or substantial portions of the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
# THE SOFTWARE.
25+
"""
26+
``adafruit_pn532.i2c``
27+
====================================================
28+
29+
This module will let you communicate with a PN532 RFID/NFC shield or breakout
30+
using I2C.
31+
32+
* Author(s): Original Raspberry Pi code by Tony DiCola, CircuitPython by ladyada,
33+
refactor by Carter Nelson
34+
35+
"""
36+
37+
__version__ = "0.0.0-auto.0"
38+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
39+
40+
import time
41+
import adafruit_bus_device.i2c_device as i2c_device
42+
from digitalio import Direction
43+
from micropython import const
44+
from adafruit_pn532.adafruit_pn532 import PN532, BusyError, _reset
45+
46+
# pylint: disable=bad-whitespace
47+
_I2C_ADDRESS = const(0x24)
48+
49+
class PN532_I2C(PN532):
50+
"""Driver for the PN532 connected over I2C."""
51+
def __init__(self, i2c, *, irq=None, reset=None, req=None, debug=False):
52+
"""Create an instance of the PN532 class using I2C. Note that PN532
53+
uses clock stretching. Optional IRQ pin (not used),
54+
reset pin and debugging output.
55+
"""
56+
self.debug = debug
57+
self._irq = irq
58+
self._req = req
59+
if reset:
60+
_reset(reset)
61+
self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
62+
super().__init__(debug=debug, reset=reset)
63+
64+
def _wakeup(self): # pylint: disable=no-self-use
65+
"""Send any special commands/data to wake up PN532"""
66+
if self._req:
67+
self._req.direction = Direction.OUTPUT
68+
self._req.value = True
69+
time.sleep(0.1)
70+
self._req.value = False
71+
time.sleep(0.1)
72+
self._req.value = True
73+
time.sleep(0.5)
74+
75+
def _wait_ready(self, timeout=1):
76+
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
77+
status = bytearray(1)
78+
timestamp = time.monotonic()
79+
while (time.monotonic() - timestamp) < timeout:
80+
try:
81+
with self._i2c:
82+
self._i2c.readinto(status)
83+
except OSError:
84+
self._wakeup()
85+
continue
86+
if status == b'\x01':
87+
return True # No longer busy
88+
else:
89+
time.sleep(0.05) # lets ask again soon!
90+
# Timed out!
91+
return False
92+
93+
def _read_data(self, count):
94+
"""Read a specified count of bytes from the PN532."""
95+
# Build a read request frame.
96+
frame = bytearray(count+1)
97+
with self._i2c as i2c:
98+
i2c.readinto(frame, end=1) # read status byte!
99+
if frame[0] != 0x01: # not ready
100+
raise BusyError
101+
i2c.readinto(frame) # ok get the data, plus statusbyte
102+
if self.debug:
103+
print("Reading: ", [hex(i) for i in frame[1:]])
104+
else:
105+
time.sleep(0.1)
106+
return frame[1:] # don't return the status byte
107+
108+
def _write_data(self, framebytes):
109+
"""Write a specified count of bytes to the PN532"""
110+
with self._i2c as i2c:
111+
i2c.write(framebytes)

0 commit comments

Comments
 (0)