Merge pull request #64 from tcfranks/main
resubmit pr Typting Annotations
This commit is contained in:
commit
0061f33008
5 changed files with 124 additions and 47 deletions
|
@ -31,6 +31,14 @@ from digitalio import Direction
|
||||||
|
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Optional, Tuple, Union
|
||||||
|
from typing_extensions import Literal
|
||||||
|
from circuitpython_typing import ReadableBuffer
|
||||||
|
from digitalio import DigitalInOut # pylint: disable=ungrouped-imports
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
__version__ = "0.0.0+auto.0"
|
__version__ = "0.0.0+auto.0"
|
||||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
||||||
|
|
||||||
|
@ -151,7 +159,13 @@ class BusyError(Exception):
|
||||||
class PN532:
|
class PN532:
|
||||||
"""PN532 driver base, must be extended for I2C/SPI/UART interfacing"""
|
"""PN532 driver base, must be extended for I2C/SPI/UART interfacing"""
|
||||||
|
|
||||||
def __init__(self, *, debug=False, irq=None, reset=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
debug: bool = False,
|
||||||
|
irq: Optional[DigitalInOut] = None,
|
||||||
|
reset: Optional[DigitalInOut] = None
|
||||||
|
) -> None:
|
||||||
"""Create an instance of the PN532 class"""
|
"""Create an instance of the PN532 class"""
|
||||||
self.low_power = True
|
self.low_power = True
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
@ -160,26 +174,26 @@ class PN532:
|
||||||
self.reset()
|
self.reset()
|
||||||
_ = self.firmware_version
|
_ = self.firmware_version
|
||||||
|
|
||||||
def _read_data(self, count):
|
def _read_data(self, count: int) -> Union[bytes, bytearray]:
|
||||||
# Read raw data from device, not including status bytes:
|
# Read raw data from device, not including status bytes:
|
||||||
# Subclasses MUST implement this!
|
# Subclasses MUST implement this!
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _write_data(self, framebytes):
|
def _write_data(self, framebytes: bytes) -> None:
|
||||||
# Write raw bytestring data to device, not including status bytes:
|
# Write raw bytestring data to device, not including status bytes:
|
||||||
# Subclasses MUST implement this!
|
# Subclasses MUST implement this!
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _wait_ready(self, timeout):
|
def _wait_ready(self, timeout: float) -> bool:
|
||||||
# Check if busy up to max length of 'timeout' seconds
|
# Check if busy up to max length of 'timeout' seconds
|
||||||
# Subclasses MUST implement this!
|
# Subclasses MUST implement this!
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _wakeup(self):
|
def _wakeup(self) -> None:
|
||||||
# Send special command to wake up
|
# Send special command to wake up
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def reset(self):
|
def reset(self) -> None:
|
||||||
"""Perform a hardware reset toggle and then wake up the PN532"""
|
"""Perform a hardware reset toggle and then wake up the PN532"""
|
||||||
if self._reset_pin:
|
if self._reset_pin:
|
||||||
if self.debug:
|
if self.debug:
|
||||||
|
@ -191,7 +205,7 @@ class PN532:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
self._wakeup()
|
self._wakeup()
|
||||||
|
|
||||||
def _write_frame(self, data):
|
def _write_frame(self, data: bytearray) -> None:
|
||||||
"""Write a frame to the PN532 with the specified data bytearray."""
|
"""Write a frame to the PN532 with the specified data bytearray."""
|
||||||
assert (
|
assert (
|
||||||
data is not None and 1 < len(data) < 255
|
data is not None and 1 < len(data) < 255
|
||||||
|
@ -221,7 +235,7 @@ class PN532:
|
||||||
print("Write frame: ", [hex(i) for i in frame])
|
print("Write frame: ", [hex(i) for i in frame])
|
||||||
self._write_data(bytes(frame))
|
self._write_data(bytes(frame))
|
||||||
|
|
||||||
def _read_frame(self, length):
|
def _read_frame(self, length: int) -> Union[bytes, bytearray]:
|
||||||
"""Read a response frame from the PN532 of at most length bytes in size.
|
"""Read a response frame from the PN532 of at most length bytes in size.
|
||||||
Returns the data inside the frame if found, otherwise raises an exception
|
Returns the data inside the frame if found, otherwise raises an exception
|
||||||
if there is an error parsing the frame. Note that less than length bytes
|
if there is an error parsing the frame. Note that less than length bytes
|
||||||
|
@ -257,8 +271,12 @@ class PN532:
|
||||||
return response[offset + 2 : offset + 2 + frame_len]
|
return response[offset + 2 : offset + 2 + frame_len]
|
||||||
|
|
||||||
def call_function(
|
def call_function(
|
||||||
self, command, response_length=0, params=[], timeout=1
|
self,
|
||||||
): # pylint: disable=dangerous-default-value
|
command: int,
|
||||||
|
response_length: int = 0,
|
||||||
|
params: ReadableBuffer = b"",
|
||||||
|
timeout: float = 1,
|
||||||
|
) -> Optional[Union[bytes, bytearray]]:
|
||||||
"""Send specified command to the PN532 and expect up to response_length
|
"""Send specified command to the PN532 and expect up to response_length
|
||||||
bytes back in a response. Note that less than the expected bytes might
|
bytes back in a response. Note that less than the expected bytes might
|
||||||
be returned! Params can optionally specify an array of bytes to send as
|
be returned! Params can optionally specify an array of bytes to send as
|
||||||
|
@ -273,11 +291,11 @@ class PN532:
|
||||||
)
|
)
|
||||||
|
|
||||||
def send_command(
|
def send_command(
|
||||||
self, command, params=[], timeout=1
|
self, command: int, params: ReadableBuffer = b"", timeout: float = 1
|
||||||
): # pylint: disable=dangerous-default-value
|
) -> bool:
|
||||||
"""Send specified command to the PN532 and wait for an acknowledgment.
|
"""Send specified command to the PN532 and wait for an acknowledgment.
|
||||||
Will wait up to timeout seconds for the acknowlegment and return True.
|
Will wait up to timeout seconds for the acknowledgment and return True.
|
||||||
If no acknowlegment is received, False is returned.
|
If no acknowledgment is received, False is returned.
|
||||||
"""
|
"""
|
||||||
if self.low_power:
|
if self.low_power:
|
||||||
self._wakeup()
|
self._wakeup()
|
||||||
|
@ -300,7 +318,9 @@ class PN532:
|
||||||
raise RuntimeError("Did not receive expected ACK from PN532!")
|
raise RuntimeError("Did not receive expected ACK from PN532!")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def process_response(self, command, response_length=0, timeout=1):
|
def process_response(
|
||||||
|
self, command: int, response_length: int = 0, timeout: float = 1
|
||||||
|
) -> Optional[Union[bytes, bytearray]]:
|
||||||
"""Process the response from the PN532 and expect up to response_length
|
"""Process the response from the PN532 and expect up to response_length
|
||||||
bytes back in a response. Note that less than the expected bytes might
|
bytes back in a response. Note that less than the expected bytes might
|
||||||
be returned! Will wait up to timeout seconds for a response and return
|
be returned! Will wait up to timeout seconds for a response and return
|
||||||
|
@ -317,7 +337,7 @@ class PN532:
|
||||||
# Return response data.
|
# Return response data.
|
||||||
return response[2:]
|
return response[2:]
|
||||||
|
|
||||||
def power_down(self):
|
def power_down(self) -> bool:
|
||||||
"""Put the PN532 into a low power state. If the reset pin is connected a
|
"""Put the PN532 into a low power state. If the reset pin is connected a
|
||||||
hard power down is performed, if not, a soft power down is performed
|
hard power down is performed, if not, a soft power down is performed
|
||||||
instead. Returns True if the PN532 was powered down successfully or
|
instead. Returns True if the PN532 was powered down successfully or
|
||||||
|
@ -333,7 +353,7 @@ class PN532:
|
||||||
return self.low_power
|
return self.low_power
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def firmware_version(self):
|
def firmware_version(self) -> Tuple[int, int, int, int]:
|
||||||
"""Call PN532 GetFirmwareVersion function and return a tuple with the IC,
|
"""Call PN532 GetFirmwareVersion function and return a tuple with the IC,
|
||||||
Ver, Rev, and Support values.
|
Ver, Rev, and Support values.
|
||||||
"""
|
"""
|
||||||
|
@ -342,7 +362,7 @@ class PN532:
|
||||||
raise RuntimeError("Failed to detect the PN532")
|
raise RuntimeError("Failed to detect the PN532")
|
||||||
return tuple(response)
|
return tuple(response)
|
||||||
|
|
||||||
def SAM_configuration(self): # pylint: disable=invalid-name
|
def SAM_configuration(self) -> None: # pylint: disable=invalid-name
|
||||||
"""Configure the PN532 to read MiFare cards."""
|
"""Configure the PN532 to read MiFare cards."""
|
||||||
# Send SAM configuration command with configuration for:
|
# Send SAM configuration command with configuration for:
|
||||||
# - 0x01, normal mode
|
# - 0x01, normal mode
|
||||||
|
@ -352,7 +372,9 @@ class PN532:
|
||||||
# check the command was executed as expected.
|
# check the command was executed as expected.
|
||||||
self.call_function(_COMMAND_SAMCONFIGURATION, params=[0x01, 0x14, 0x01])
|
self.call_function(_COMMAND_SAMCONFIGURATION, params=[0x01, 0x14, 0x01])
|
||||||
|
|
||||||
def read_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
|
def read_passive_target(
|
||||||
|
self, card_baud: int = _MIFARE_ISO14443A, timeout: float = 1
|
||||||
|
) -> Optional[bytearray]:
|
||||||
"""Wait for a MiFare card to be available and return its UID when found.
|
"""Wait for a MiFare card to be available and return its UID when found.
|
||||||
Will wait up to timeout seconds and return None if no card is found,
|
Will wait up to timeout seconds and return None if no card is found,
|
||||||
otherwise a bytearray with the UID of the found card is returned.
|
otherwise a bytearray with the UID of the found card is returned.
|
||||||
|
@ -364,9 +386,11 @@ class PN532:
|
||||||
return None
|
return None
|
||||||
return self.get_passive_target(timeout=timeout)
|
return self.get_passive_target(timeout=timeout)
|
||||||
|
|
||||||
def listen_for_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
|
def listen_for_passive_target(
|
||||||
|
self, card_baud: int = _MIFARE_ISO14443A, timeout: float = 1
|
||||||
|
) -> bool:
|
||||||
"""Send command to PN532 to begin listening for a Mifare card. This
|
"""Send command to PN532 to begin listening for a Mifare card. This
|
||||||
returns True if the command was received succesfully. Note, this does
|
returns True if the command was received successfully. Note, this does
|
||||||
not also return the UID of a card! `get_passive_target` must be called
|
not also return the UID of a card! `get_passive_target` must be called
|
||||||
to read the UID when a card is found. If just looking to see if a card
|
to read the UID when a card is found. If just looking to see if a card
|
||||||
is currently present use `read_passive_target` instead.
|
is currently present use `read_passive_target` instead.
|
||||||
|
@ -380,7 +404,9 @@ class PN532:
|
||||||
return False # _COMMAND_INLISTPASSIVETARGET failed
|
return False # _COMMAND_INLISTPASSIVETARGET failed
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def get_passive_target(self, timeout=1):
|
def get_passive_target(
|
||||||
|
self, timeout: float = 1
|
||||||
|
) -> Optional[Union[bytes, bytearray]]:
|
||||||
"""Will wait up to timeout seconds and return None if no card is found,
|
"""Will wait up to timeout seconds and return None if no card is found,
|
||||||
otherwise a bytearray with the UID of the found card is returned.
|
otherwise a bytearray with the UID of the found card is returned.
|
||||||
`listen_for_passive_target` must have been called first in order to put
|
`listen_for_passive_target` must have been called first in order to put
|
||||||
|
@ -404,9 +430,13 @@ class PN532:
|
||||||
# Return UID of card.
|
# Return UID of card.
|
||||||
return response[6 : 6 + response[5]]
|
return response[6 : 6 + response[5]]
|
||||||
|
|
||||||
def mifare_classic_authenticate_block(
|
def mifare_classic_authenticate_block( # pylint: disable=invalid-name
|
||||||
self, uid, block_number, key_number, key
|
self,
|
||||||
): # pylint: disable=invalid-name
|
uid: ReadableBuffer,
|
||||||
|
block_number: int,
|
||||||
|
key_number: Literal[0x60, 0x61],
|
||||||
|
key: ReadableBuffer,
|
||||||
|
) -> bool:
|
||||||
"""Authenticate specified block number for a MiFare classic card. Uid
|
"""Authenticate specified block number for a MiFare classic card. Uid
|
||||||
should be a byte array with the UID of the card, block number should be
|
should be a byte array with the UID of the card, block number should be
|
||||||
the block to authenticate, key number should be the key type (like
|
the block to authenticate, key number should be the key type (like
|
||||||
|
@ -429,7 +459,9 @@ class PN532:
|
||||||
)
|
)
|
||||||
return response[0] == 0x00
|
return response[0] == 0x00
|
||||||
|
|
||||||
def mifare_classic_read_block(self, block_number):
|
def mifare_classic_read_block(
|
||||||
|
self, block_number: int
|
||||||
|
) -> Optional[Union[bytes, bytearray]]:
|
||||||
"""Read a block of data from the card. Block number should be the block
|
"""Read a block of data from the card. Block number should be the block
|
||||||
to read. If the block is successfully read a bytearray of length 16 with
|
to read. If the block is successfully read a bytearray of length 16 with
|
||||||
data starting at the specified block will be returned. If the block is
|
data starting at the specified block will be returned. If the block is
|
||||||
|
@ -447,7 +479,9 @@ class PN532:
|
||||||
# Return first 4 bytes since 16 bytes are always returned.
|
# Return first 4 bytes since 16 bytes are always returned.
|
||||||
return response[1:]
|
return response[1:]
|
||||||
|
|
||||||
def mifare_classic_write_block(self, block_number, data):
|
def mifare_classic_write_block(
|
||||||
|
self, block_number: int, data: ReadableBuffer
|
||||||
|
) -> bool:
|
||||||
"""Write a block of data to the card. Block number should be the block
|
"""Write a block of data to the card. Block number should be the block
|
||||||
to write and data should be a byte array of length 16 with the data to
|
to write and data should be a byte array of length 16 with the data to
|
||||||
write. If the data is successfully written then True is returned,
|
write. If the data is successfully written then True is returned,
|
||||||
|
@ -468,7 +502,7 @@ class PN532:
|
||||||
)
|
)
|
||||||
return response[0] == 0x0
|
return response[0] == 0x0
|
||||||
|
|
||||||
def ntag2xx_write_block(self, block_number, data):
|
def ntag2xx_write_block(self, block_number: int, data: ReadableBuffer) -> bool:
|
||||||
"""Write a block of data to the card. Block number should be the block
|
"""Write a block of data to the card. Block number should be the block
|
||||||
to write and data should be a byte array of length 4 with the data to
|
to write and data should be a byte array of length 4 with the data to
|
||||||
write. If the data is successfully written then True is returned,
|
write. If the data is successfully written then True is returned,
|
||||||
|
@ -487,7 +521,9 @@ class PN532:
|
||||||
)
|
)
|
||||||
return response[0] == 0x00
|
return response[0] == 0x00
|
||||||
|
|
||||||
def ntag2xx_read_block(self, block_number):
|
def ntag2xx_read_block(
|
||||||
|
self, block_number: int
|
||||||
|
) -> Optional[Union[bytes, bytearray]]:
|
||||||
"""Read a block of data from the card. Block number should be the block
|
"""Read a block of data from the card. Block number should be the block
|
||||||
to read. If the block is successfully read the first 4 bytes (after the
|
to read. If the block is successfully read the first 4 bytes (after the
|
||||||
leading 0x00 byte) will be returned.
|
leading 0x00 byte) will be returned.
|
||||||
|
|
|
@ -23,6 +23,13 @@ from digitalio import Direction
|
||||||
from micropython import const
|
from micropython import const
|
||||||
from adafruit_pn532.adafruit_pn532 import PN532, BusyError
|
from adafruit_pn532.adafruit_pn532 import PN532, BusyError
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Optional
|
||||||
|
from digitalio import DigitalInOut # pylint: disable=ungrouped-imports
|
||||||
|
from busio import I2C
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
_I2C_ADDRESS = const(0x24)
|
_I2C_ADDRESS = const(0x24)
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,8 +37,15 @@ class PN532_I2C(PN532):
|
||||||
"""Driver for the PN532 connected over I2C."""
|
"""Driver for the PN532 connected over I2C."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, i2c, address=_I2C_ADDRESS, *, irq=None, reset=None, req=None, debug=False
|
self,
|
||||||
):
|
i2c: I2C,
|
||||||
|
address: int = _I2C_ADDRESS,
|
||||||
|
*,
|
||||||
|
irq: Optional[DigitalInOut] = None,
|
||||||
|
reset: Optional[DigitalInOut] = None,
|
||||||
|
req: Optional[DigitalInOut] = None,
|
||||||
|
debug: bool = False
|
||||||
|
) -> None:
|
||||||
"""Create an instance of the PN532 class using I2C. Note that PN532
|
"""Create an instance of the PN532 class using I2C. Note that PN532
|
||||||
uses clock stretching. Optional IRQ pin (not used),
|
uses clock stretching. Optional IRQ pin (not used),
|
||||||
resetp pin and debugging output.
|
resetp pin and debugging output.
|
||||||
|
@ -41,7 +55,7 @@ class PN532_I2C(PN532):
|
||||||
self._i2c = i2c_device.I2CDevice(i2c, address)
|
self._i2c = i2c_device.I2CDevice(i2c, address)
|
||||||
super().__init__(debug=debug, irq=irq, reset=reset)
|
super().__init__(debug=debug, irq=irq, reset=reset)
|
||||||
|
|
||||||
def _wakeup(self):
|
def _wakeup(self) -> None:
|
||||||
"""Send any special commands/data to wake up PN532"""
|
"""Send any special commands/data to wake up PN532"""
|
||||||
if self._reset_pin:
|
if self._reset_pin:
|
||||||
self._reset_pin.value = True
|
self._reset_pin.value = True
|
||||||
|
@ -55,7 +69,7 @@ class PN532_I2C(PN532):
|
||||||
self.low_power = False
|
self.low_power = False
|
||||||
self.SAM_configuration() # Put the PN532 back in normal mode
|
self.SAM_configuration() # Put the PN532 back in normal mode
|
||||||
|
|
||||||
def _wait_ready(self, timeout=1):
|
def _wait_ready(self, timeout: float = 1) -> bool:
|
||||||
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
|
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
|
||||||
status = bytearray(1)
|
status = bytearray(1)
|
||||||
timestamp = time.monotonic()
|
timestamp = time.monotonic()
|
||||||
|
@ -67,11 +81,11 @@ class PN532_I2C(PN532):
|
||||||
continue
|
continue
|
||||||
if status == b"\x01":
|
if status == b"\x01":
|
||||||
return True # No longer busy
|
return True # No longer busy
|
||||||
time.sleep(0.01) # lets ask again soon!
|
time.sleep(0.01) # let's ask again soon!
|
||||||
# Timed out!
|
# Timed out!
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _read_data(self, count):
|
def _read_data(self, count: int) -> bytearray:
|
||||||
"""Read a specified count of bytes from the PN532."""
|
"""Read a specified count of bytes from the PN532."""
|
||||||
# Build a read request frame.
|
# Build a read request frame.
|
||||||
frame = bytearray(count + 1)
|
frame = bytearray(count + 1)
|
||||||
|
@ -84,7 +98,7 @@ class PN532_I2C(PN532):
|
||||||
print("Reading: ", [hex(i) for i in frame[1:]])
|
print("Reading: ", [hex(i) for i in frame[1:]])
|
||||||
return frame[1:] # don't return the status byte
|
return frame[1:] # don't return the status byte
|
||||||
|
|
||||||
def _write_data(self, framebytes):
|
def _write_data(self, framebytes: bytes) -> None:
|
||||||
"""Write a specified count of bytes to the PN532"""
|
"""Write a specified count of bytes to the PN532"""
|
||||||
with self._i2c as i2c:
|
with self._i2c as i2c:
|
||||||
i2c.write(framebytes)
|
i2c.write(framebytes)
|
||||||
|
|
|
@ -14,6 +14,14 @@ using SPI.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Optional
|
||||||
|
from circuitpython_typing import ReadableBuffer
|
||||||
|
from digitalio import DigitalInOut
|
||||||
|
from busio import SPI
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
__version__ = "0.0.0+auto.0"
|
__version__ = "0.0.0+auto.0"
|
||||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
||||||
|
|
||||||
|
@ -28,7 +36,7 @@ _SPI_DATAREAD = const(0x03)
|
||||||
_SPI_READY = const(0x01)
|
_SPI_READY = const(0x01)
|
||||||
|
|
||||||
|
|
||||||
def reverse_bit(num):
|
def reverse_bit(num: int) -> int:
|
||||||
"""Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
|
"""Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
|
||||||
it is LSB for the PN532, but 99% of SPI implementations are MSB only!"""
|
it is LSB for the PN532, but 99% of SPI implementations are MSB only!"""
|
||||||
result = 0
|
result = 0
|
||||||
|
@ -44,13 +52,21 @@ class PN532_SPI(PN532):
|
||||||
SPI device & chip select digitalInOut pin. Optional IRQ pin (not used),
|
SPI device & chip select digitalInOut pin. Optional IRQ pin (not used),
|
||||||
reset pin and debugging output."""
|
reset pin and debugging output."""
|
||||||
|
|
||||||
def __init__(self, spi, cs_pin, *, irq=None, reset=None, debug=False):
|
def __init__(
|
||||||
|
self,
|
||||||
|
spi: SPI,
|
||||||
|
cs_pin: DigitalInOut,
|
||||||
|
*,
|
||||||
|
irq: Optional[DigitalInOut] = None,
|
||||||
|
reset: Optional[DigitalInOut] = None,
|
||||||
|
debug: bool = False
|
||||||
|
) -> None:
|
||||||
"""Create an instance of the PN532 class using SPI"""
|
"""Create an instance of the PN532 class using SPI"""
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self._spi = spi_device.SPIDevice(spi, cs_pin)
|
self._spi = spi_device.SPIDevice(spi, cs_pin)
|
||||||
super().__init__(debug=debug, irq=irq, reset=reset)
|
super().__init__(debug=debug, irq=irq, reset=reset)
|
||||||
|
|
||||||
def _wakeup(self):
|
def _wakeup(self) -> None:
|
||||||
"""Send any special commands/data to wake up PN532"""
|
"""Send any special commands/data to wake up PN532"""
|
||||||
if self._reset_pin:
|
if self._reset_pin:
|
||||||
self._reset_pin.value = True
|
self._reset_pin.value = True
|
||||||
|
@ -61,7 +77,7 @@ class PN532_SPI(PN532):
|
||||||
self.low_power = False
|
self.low_power = False
|
||||||
self.SAM_configuration() # Put the PN532 back in normal mode
|
self.SAM_configuration() # Put the PN532 back in normal mode
|
||||||
|
|
||||||
def _wait_ready(self, timeout=1):
|
def _wait_ready(self, timeout: float = 1) -> bool:
|
||||||
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
|
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
|
||||||
status_cmd = bytearray([reverse_bit(_SPI_STATREAD), 0x00])
|
status_cmd = bytearray([reverse_bit(_SPI_STATREAD), 0x00])
|
||||||
status_response = bytearray([0x00, 0x00])
|
status_response = bytearray([0x00, 0x00])
|
||||||
|
@ -77,7 +93,7 @@ class PN532_SPI(PN532):
|
||||||
# We timed out!
|
# We timed out!
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _read_data(self, count):
|
def _read_data(self, count: int) -> bytearray:
|
||||||
"""Read a specified count of bytes from the PN532."""
|
"""Read a specified count of bytes from the PN532."""
|
||||||
# Build a read request frame.
|
# Build a read request frame.
|
||||||
frame = bytearray(count + 1)
|
frame = bytearray(count + 1)
|
||||||
|
@ -92,7 +108,7 @@ class PN532_SPI(PN532):
|
||||||
print("Reading: ", [hex(i) for i in frame[1:]])
|
print("Reading: ", [hex(i) for i in frame[1:]])
|
||||||
return frame[1:]
|
return frame[1:]
|
||||||
|
|
||||||
def _write_data(self, framebytes):
|
def _write_data(self, framebytes: ReadableBuffer) -> None:
|
||||||
"""Write a specified count of bytes to the PN532"""
|
"""Write a specified count of bytes to the PN532"""
|
||||||
# start by making a frame with data write in front,
|
# start by making a frame with data write in front,
|
||||||
# then rest of bytes, and LSBify it
|
# then rest of bytes, and LSBify it
|
||||||
|
|
|
@ -17,6 +17,13 @@ using UART.
|
||||||
__version__ = "0.0.0+auto.0"
|
__version__ = "0.0.0+auto.0"
|
||||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Optional
|
||||||
|
from circuitpython_typing import ReadableBuffer
|
||||||
|
from digitalio import DigitalInOut
|
||||||
|
from busio import UART
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from adafruit_pn532.adafruit_pn532 import PN532, BusyError
|
from adafruit_pn532.adafruit_pn532 import PN532, BusyError
|
||||||
|
@ -25,7 +32,9 @@ from adafruit_pn532.adafruit_pn532 import PN532, BusyError
|
||||||
class PN532_UART(PN532):
|
class PN532_UART(PN532):
|
||||||
"""Driver for the PN532 connected over Serial UART"""
|
"""Driver for the PN532 connected over Serial UART"""
|
||||||
|
|
||||||
def __init__(self, uart, *, reset=None, debug=False):
|
def __init__(
|
||||||
|
self, uart: UART, *, reset: Optional[DigitalInOut] = None, debug: bool = False
|
||||||
|
) -> None:
|
||||||
"""Create an instance of the PN532 class using Serial connection.
|
"""Create an instance of the PN532 class using Serial connection.
|
||||||
Optional reset pin and debugging output.
|
Optional reset pin and debugging output.
|
||||||
"""
|
"""
|
||||||
|
@ -33,7 +42,7 @@ class PN532_UART(PN532):
|
||||||
self._uart = uart
|
self._uart = uart
|
||||||
super().__init__(debug=debug, reset=reset)
|
super().__init__(debug=debug, reset=reset)
|
||||||
|
|
||||||
def _wakeup(self):
|
def _wakeup(self) -> None:
|
||||||
"""Send any special commands/data to wake up PN532"""
|
"""Send any special commands/data to wake up PN532"""
|
||||||
if self._reset_pin:
|
if self._reset_pin:
|
||||||
self._reset_pin.value = True
|
self._reset_pin.value = True
|
||||||
|
@ -44,7 +53,7 @@ class PN532_UART(PN532):
|
||||||
) # wake up!
|
) # wake up!
|
||||||
self.SAM_configuration()
|
self.SAM_configuration()
|
||||||
|
|
||||||
def _wait_ready(self, timeout=1):
|
def _wait_ready(self, timeout: float = 1) -> bool:
|
||||||
"""Wait `timeout` seconds"""
|
"""Wait `timeout` seconds"""
|
||||||
timestamp = time.monotonic()
|
timestamp = time.monotonic()
|
||||||
while (time.monotonic() - timestamp) < timeout:
|
while (time.monotonic() - timestamp) < timeout:
|
||||||
|
@ -54,7 +63,7 @@ class PN532_UART(PN532):
|
||||||
# Timed out!
|
# Timed out!
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _read_data(self, count):
|
def _read_data(self, count: int) -> bytes:
|
||||||
"""Read a specified count of bytes from the PN532."""
|
"""Read a specified count of bytes from the PN532."""
|
||||||
frame = self._uart.read(count)
|
frame = self._uart.read(count)
|
||||||
if not frame:
|
if not frame:
|
||||||
|
@ -63,7 +72,7 @@ class PN532_UART(PN532):
|
||||||
print("Reading: ", [hex(i) for i in frame])
|
print("Reading: ", [hex(i) for i in frame])
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def _write_data(self, framebytes):
|
def _write_data(self, framebytes: ReadableBuffer) -> None:
|
||||||
"""Write a specified count of bytes to the PN532"""
|
"""Write a specified count of bytes to the PN532"""
|
||||||
self._uart.reset_input_buffer()
|
self._uart.reset_input_buffer()
|
||||||
self._uart.write(framebytes)
|
self._uart.write(framebytes)
|
||||||
|
|
|
@ -4,4 +4,6 @@
|
||||||
|
|
||||||
Adafruit-Blinka
|
Adafruit-Blinka
|
||||||
adafruit-circuitpython-busdevice
|
adafruit-circuitpython-busdevice
|
||||||
|
adafruit-circuitpython-typing
|
||||||
pyserial
|
pyserial
|
||||||
|
typing-extensions~=4.0
|
||||||
|
|
Loading…
Reference in a new issue