MicroPython_PN532/pn532/i2c.py
Kumi ef5c8c4a1d
Migrate library to MicroPython compatibility
Changes include adapting codebases for I2C, SPI, and UART modules to work with MicroPython's machine library. Removed references to CircuitPython-specific libraries and updated configurations for Pin and UART initialization. Simplified import statements and replaced ReadableBuffer type hints with MicroPython's bytes and bytearray types. This migration targets increased accessibility for MicroPython users, ensuring broader hardware support while maintaining core RFID/NFC functionalities. Adjustments also involve file structure and documentation revisions to reflect the MicroPython focus.
2024-01-11 16:51:27 +01:00

130 lines
4.5 KiB
Python

# SPDX-FileCopyrightText: 2015-2018 Tony DiCola for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
``adafruit_pn532.i2c``
====================================================
This module will let you communicate with a PN532 RFID/NFC shield or breakout
using I2C.
* Author(s): Original Raspberry Pi code by Tony DiCola, CircuitPython by ladyada,
refactor by Carter Nelson
"""
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
import time
from machine import I2C, Pin
from micropython import const
from pn532.pn532 import PN532, BusyError
try:
from typing import Optional, Union
except ImportError:
pass
_I2C_ADDRESS = const(0x24)
class PN532_I2C(PN532):
"""Driver for the PN532 connected over I2C."""
def __init__(
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
uses clock stretching. Optional IRQ pin (not used),
resetp pin and debugging output.
:param ~busio.I2C i2c: The I2C bus the PN532 is connected to.
:param int address: The I2C device address. Defaults to :const:`0x24`
:param digitalio.DigitalInOut irq: board pin the PN532 IRQ is connected to
:param digitalio.DigitalInOut reset: board pin the PN532 RSTOUT_N is connected to
:param digitalio.DigitalInOut req: board pin the PN532 P32 is connected to
:param bool debug: if True print additional debug statements. Defaults to False
**Quickstart: Importing and using the device**
Here is an example of using the :class:`PN532_I2C` class.
First you will need to import the libraries to use the sensor
Once this is done you can define your `board.I2C` object and define your object
.. code-block:: python
i2c = machine.I2C(0, scl=SCL_PIN, sda=SDA_PIN)
pn532 = PN532_I2C(i2c, debug=False, reset=RESET_PIN, req=REQ_PIN)
# Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration()
Now you have access to the attributes and functions of the PN532 RFID/NFC
shield or breakout
.. code-block:: python
uid = pn532.read_passive_target(timeout=0.5)
"""
self.debug = debug
self._req = req
self._i2c = i2c
super().__init__(debug=debug, irq=irq, reset=reset)
def _wakeup(self) -> None:
"""Send any special commands/data to wake up PN532"""
if self._reset_pin:
self._reset_pin.value = True
time.sleep(0.01)
if self._req:
self._req.direction = Direction.OUTPUT
self._req.value(False)
time.sleep(0.01)
self._req.value(True)
time.sleep(0.01)
self.low_power = False
self.SAM_configuration() # Put the PN532 back in normal mode
def _wait_ready(self, timeout: float = 1) -> bool:
"""Poll PN532 if status byte is ready, up to `timeout` seconds"""
status = bytearray(1)
timestamp = time.monotonic()
while (time.monotonic() - timestamp) < timeout:
try:
with self._i2c:
self._i2c.readfrom_into(address, status)
except OSError:
continue
if status == b"\x01":
return True # No longer busy
time.sleep(0.01) # let's ask again soon!
# Timed out!
return False
def _read_data(self, count: int) -> bytearray:
"""Read a specified count of bytes from the PN532."""
# Build a read request frame.
frame = bytearray(count + 1)
with self._i2c as i2c:
i2c.readfrom_into(address, frame, stop=1) # read status byte!
if frame[0] != 0x01: # not ready
raise BusyError
i2c.readfrom_into(address, frame) # ok get the data, plus statusbyte
if self.debug:
print("Reading: ", [hex(i) for i in frame[1:]])
return frame[1:] # don't return the status byte
def _write_data(self, framebytes: bytes) -> None:
"""Write a specified count of bytes to the PN532"""
with self._i2c as i2c:
i2c.writeto(address, framebytes)