diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..4ceb55c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +.github/ export-ignore +.gitattributes export-ignore +.gitignore export-ignore + +.travis.yml export-ignore + +doc/*.doc export-ignore + +*.h text diff=cpp linguist-language=C++ +*.ino text diff=cpp linguist-language=C++ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index aa1bbcbf..de0e077b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,10 @@ | Q | A diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..59d8d36c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "quarterly" + timezone: "Europe/Berlin" + time: "05:00" + labels: + - "github-actions-dependencies" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/autoreview.yml b/.github/workflows/autoreview.yml new file mode 100644 index 00000000..ee51d8f0 --- /dev/null +++ b/.github/workflows/autoreview.yml @@ -0,0 +1,12 @@ +name: autoreview +on: [pull_request] + +jobs: + misspellcheck: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Run misspell with reviewdog + uses: reviewdog/action-misspell@v1 + #with: + # pattern: "*.md" diff --git a/.github/workflows/test.platformio.yml b/.github/workflows/test.platformio.yml new file mode 100644 index 00000000..419ee3cb --- /dev/null +++ b/.github/workflows/test.platformio.yml @@ -0,0 +1,63 @@ +name: PlatformIO CI + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-24.04 + timeout-minutes: 10 + strategy: + fail-fast: false + max-parallel: 20 + matrix: + boards: ['all'] + example: [ + ChangeUID, + DumpInfo, + firmware_check, + FixBrickedUID, + MifareClassicValueBlock, + MinimalInterrupt, + ReadUidMultiReader, + rfid_default_keys, + rfid_write_personal_data, + Ntag216_AUTH, + ReadNUID, + RFID-Cloner, + rfid_read_personal_data, + ] + #include: + # - boards: 'avr_only' + # example: AccessControl + + steps: + - uses: actions/checkout@v6 + - name: Cache pip + uses: actions/cache@v5 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: ${{ runner.os }}-pip- + - name: Cache PlatformIO + uses: actions/cache@v5 + with: + path: ~/.platformio + key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} + - name: Set up Python + uses: actions/setup-python@v6 + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + - name: Run PlatformIO all Boards + if: ${{ contains(matrix.boards, 'all') }} + # test all + run: platformio ci --lib=. --board=uno --board=megaatmega1280 --board=due --board=zero --board=d1_mini + env: + PLATFORMIO_CI_SRC: examples/${{ matrix.example }}/${{ matrix.example }}.ino + - name: Run PlatformIO avr Boards + if: ${{ contains(matrix.boards, 'avr_only') }} + # test avr_only + run: platformio ci --lib=. --board=uno --board=megaatmega1280 + env: + PLATFORMIO_CI_SRC: examples/${{ matrix.example }}/${{ matrix.example }}.ino diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6c622b6a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: python -python: - - "2.7" - -# Cache PlatformIO packages using Travis CI container-based infrastructure -sudo: false -cache: - directories: - - "~/.platformio" - -env: - # add examples here and define which boards should be tested (only compile test) - - PLATFORMIO_CI_SRC=examples/ChangeUID/ChangeUID.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/DumpInfo/DumpInfo.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/firmware_check/firmware_check.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/FixBrickedUID/FixBrickedUID.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/MifareClassicValueBlock/MifareClassicValueBlock.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/MinimalInterrupt/MinimalInterrupt.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/ReadAndWrite/ReadAndWrite.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/ReadUidMultiReader/ReadUidMultiReader.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/rfid_default_keys/rfid_default_keys.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/rfid_write_personal_data/rfid_write_personal_data.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/Ntag216_AUTH/Ntag216_AUTH.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/ReadNUID/ReadNUID.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/AccessControl/AccessControl.ino TESTBOARD=arduino_avr,teensy - - PLATFORMIO_CI_SRC=examples/RFID-Cloner/RFID-Cloner.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - - PLATFORMIO_CI_SRC=examples/rfid_read_personal_data/rfid_read_personal_data.ino TESTBOARD=arduino_avr,arduino_arm,teensy,esp - -install: - - pip install -U platformio - -script: - # short the string comparison - - stringContain() { [ -z "${2##*$1*}" ]; } - # selectable board tests @Rotzbua - # prints only warnings and errors, to show all remove "1>/dev/null" - - board="arduino_avr"; if stringContain "$board" "$TESTBOARD"; then echo "check board $board"; ouput=$(platformio ci --lib=. --board=uno --board=megaatmega1280); echo "----"; echo "$ouput" | grep --quiet --ignore-case -E "^(Device|Data|Program|text|[0-9])"; else echo "skip board test of $board"; fi - - board="arduino_arm"; if stringContain "$board" "$TESTBOARD"; then echo "check board $board"; ouput=$(platformio ci --lib=. --board=due --board=zero); echo "----"; echo "$ouput" | grep --quiet --ignore-case -E "^(Device|Data|Program|text|[0-9])"; else echo "skip board test of $board"; fi - - board="teensy"; if stringContain "$board" "$TESTBOARD"; then echo "check board $board"; ouput=$(platformio ci --lib=. --board=teensy20 --board=teensy31); echo "----"; echo "$ouput" | grep --quiet --ignore-case -E "^(Device|Data|Program|text|[0-9])"; else echo "skip board test of $board"; fi - - board="esp"; if stringContain "$board" "$TESTBOARD"; then echo "check board $board"; ouput=$(platformio ci --lib=. --board=d1_mini); echo "----"; echo "$ouput" | grep --quiet --ignore-case -E "^(Device|Data|Program|text|[0-9])"; else echo "skip board test of $board"; fi diff --git a/README.rst b/README.rst index 483bac98..fbec9a84 100644 --- a/README.rst +++ b/README.rst @@ -1,12 +1,16 @@ MFRC522 ======= -.. image:: https://travis-ci.org/miguelbalboa/rfid.svg?branch=master - :target: https://travis-ci.org/miguelbalboa/rfid +.. image:: https://img.shields.io/maintenance/no/2019.svg + :target: `development`_ +.. image:: https://github.com/miguelbalboa/rfid/workflows/PlatformIO%20CI/badge.svg + :target: https://github.com/miguelbalboa/rfid/actions + :alt: GitHub Actions .. image:: https://img.shields.io/badge/C%2B%2B-11-brightgreen.svg :target: `compatible ide`_ .. image:: https://img.shields.io/github/release/miguelbalboa/rfid.svg?colorB=green :target: https://github.com/miguelbalboa/rfid/releases + :alt: Releases .. image:: https://img.shields.io/badge/ArduinoIDE-%3E%3D1.6.10-lightgrey.svg :target: `compatible ide`_ @@ -16,11 +20,22 @@ Read and write different types of Radio-Frequency IDentification (RFID) cards on your Arduino using a RC522 based reader connected via the Serial Peripheral Interface (SPI) interface. +For advanced and further development please use library `RFID_MFRC522v2 `_. .. _development: Development ----------- -**The development by owner miguelbalboa has ended**. Further development will be done by community. This library is sporadically maintained. You can make pull request if you have developed a fix. Support/issues should be solved by community. +----------- + +**The development by owner miguelbalboa has ended**. + +**Feature status: complete freeze**; no function or API change. + +**Code status: partial freeze**; just fixes/typos or documentation updates; *no* extensions for other boards; *no* new examples. + +**Maintenance status: sporadically**. + +**Why no further development?** +This library has a long history and is used in many projects. These projects often do not document what version they use. Committing changes might break those old projects and lead to bad experiences (for beginners) and support requests. For these reasons the library is in freeze mode. You can still commit typo, documentation or bug fixes. .. _before buy: @@ -35,7 +50,7 @@ If you got a bad board and you can tell us how to detect those boards (silk, chi .. _what works and not: What works and not? ----------- +------------------- * **Works** @@ -59,7 +74,6 @@ What works and not? #. Communication with smart phone, not `supported by hardware`_. #. Card emulation, not `supported by hardware`_. #. Use of IRQ pin. But there is a proof-of-concept example. - #. With Arduino Yun see `#111 `_, not supported by software. #. With Intel Galileo (Gen2) see `#310 `__, not supported by software. #. Power reduction modes `#269 `_, not supported by software. #. I2C instead of SPI `#240 `_, not supported by software. @@ -73,7 +87,7 @@ What works and not? .. _compatible ide: Compatible IDE ----------- +-------------- This library works with Arduino IDE 1.6, older versions are **not supported** and will cause compiler errors. The built-in library manager is supported. If you use your own compiler, you have to enable ``c++11``-support. @@ -81,7 +95,7 @@ If you use your own compiler, you have to enable ``c++11``-support. .. _compatible boards: Compatible boards ----------- +----------------- **!!!Only for advanced users!!!** @@ -98,7 +112,7 @@ Note that the main target/support of library is still Arduino. .. _support issue: Support/issue ----------- +------------- 1. First checkout `what works and not`_ and `troubleshooting`_ . 2. It seems to be a hardware issue or you need support to program your project? @@ -121,46 +135,49 @@ Pin Layout The following table shows the typical pin layout used: -+-----------+----------+---------------------------------------------------------------+--------------------------+ -| | PCD | Arduino | Teensy | -| +----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| | MFRC522 | Uno / 101 | Mega | Nano v3 |Leonardo / Micro | Pro Micro | 2.0 | ++ 2.0 | 3.1 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| Signal | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin | -+===========+==========+=============+=========+=========+=================+===========+========+========+========+ -| RST/Reset | RST | 9 [1]_ | 5 [1]_ | D9 | RESET / ICSP-5 | RST | 7 | 4 | 9 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| SPI SS | SDA [3]_ | 10 [2]_ | 53 [2]_ | D10 | 10 | 10 | 0 | 20 | 10 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| SPI MOSI | MOSI | 11 / ICSP-4 | 51 | D11 | ICSP-4 | 16 | 2 | 22 | 11 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| SPI MISO | MISO | 12 / ICSP-1 | 50 | D12 | ICSP-1 | 14 | 3 | 23 | 12 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ -| SPI SCK | SCK | 13 / ICSP-3 | 52 | D13 | ICSP-3 | 15 | 1 | 21 | 13 | -+-----------+----------+-------------+---------+---------+-----------------+-----------+--------+--------+--------+ - -+-----------+---------------+ -| | ESP8266 | -| +---------------+ -| | Wemos D1 mini | -+-----------+---------------+ -| Signal | Pin | -+===========+===============+ -| RST/Reset | D3 | -+-----------+---------------+ -| SPI SS | D8 | -+-----------+---------------+ -| SPI MOSI | D7 | -+-----------+---------------+ -| SPI MISO | D6 | -+-----------+---------------+ -| SPI SCK | D5 | -+-----------+---------------+ ++-----------+----------+-----------------------------------------------------------------------------------+ +| | PCD | Arduino | +| +----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| | MFRC522 | Uno / 101 | Mega | Nano v3 |Leonardo / Micro | Pro Micro | Yun [4]_| Due | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| Signal | Pin | Pin | Pin | Pin | Pin | Pin | Pin | Pin | ++===========+==========+=============+=========+=========+=================+===========+=========+=========+ +| RST/Reset | RST | 9 [1]_ | 5 [1]_ | D9 | RESET / ICSP-5 | RST | Pin9 | 22 [1]_ | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| SPI SS | SDA [3]_ | 10 [2]_ | 53 [2]_ | D10 | 10 | 10 | Pin10 | 23 [2]_ | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| SPI MOSI | MOSI | 11 / ICSP-4 | 51 | D11 | ICSP-4 | 16 | ICSP4 | SPI-4 | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| SPI MISO | MISO | 12 / ICSP-1 | 50 | D12 | ICSP-1 | 14 | ICSP1 | SPI-1 | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ +| SPI SCK | SCK | 13 / ICSP-3 | 52 | D13 | ICSP-3 | 15 | ICSP3 | SPI-3 | ++-----------+----------+-------------+---------+---------+-----------------+-----------+---------+---------+ + ++-----------+---------------+--------------------------+-------------+ +| | ESP8266 | Teensy | 8F328P-U | +| +---------------+--------+--------+--------+-------------+ +| | Wemos D1 mini | 2.0 | ++ 2.0 | 3.1 | ALPHA | ++-----------+---------------+--------+--------+--------+-------------+ +| Signal | Pin | Pin | Pin | Pin | Pin [5]_ | ++===========+===============+========+========+========+=============+ +| RST/Reset | D3 | 7 | 4 | 9 | D9# [1]_ | ++-----------+---------------+--------+--------+--------+-------------+ +| SPI SS | D8 | 0 | 20 | 10 | D10# [2]_ | ++-----------+---------------+--------+--------+--------+-------------+ +| SPI MOSI | D7 | 2 | 22 | 11 | MOSI / D11# | ++-----------+---------------+--------+--------+--------+-------------+ +| SPI MISO | D6 | 3 | 23 | 12 | MISO / D12# | ++-----------+---------------+--------+--------+--------+-------------+ +| SPI SCK | D5 | 1 | 21 | 13 | SCK | ++-----------+---------------+--------+--------+--------+-------------+ .. [1] Configurable, typically defined as RST_PIN in sketch/program. .. [2] Configurable, typically defined as SS_PIN in sketch/program. .. [3] The SDA pin might be labeled SS on some/older MFRC522 boards. +.. [4] Source: `#111 `_ . +.. [5] Pin names from the back (empty) side of the board were used as more definitive. +Important: If your micro controller supports multiple SPI interfaces, the library only uses the **default (first) SPI** of the Arduino framework. .. _hardware: Hardware @@ -218,7 +235,7 @@ Protocols .. _security: Security -------- +-------- * The **UID** of a card **can not be used** as an unique identification for security related projects. Some Chinese cards allow to change the UID which means you can easily clone a card. For projects like *access control*, *door opener* or *payment systems* you **must implement** an **additional security mechanism** like a password or normal key. * This library only supports crypto1-encrypted communication. Crypto1 has been known as `broken`_ for a few years, so it does NOT offer ANY security, it is virtually unencrypted communication. **Do not use it for any security related applications!** @@ -228,24 +245,26 @@ Security .. _troubleshooting: Troubleshooting -------- +--------------- * **I don't get input from reader** or **WARNING: Communication failure, is the MFRC522 properly connected?** #. Check your physical connection, see `Pin Layout`_ . #. Check your pin settings/variables in the code, see `Pin Layout`_ . #. Check your pin header soldering. Maybe you have cold solder joints. + #. Check your power supply. Maybe add a capacitor between 3.3V and GND to stabilize the power #560, sometimes an additional delay after `PCD_Init()` can help. #. Check voltage. Most breakouts work with 3.3V. - #. SPI only works with 3.3V, most breakouts seem 5V tollerant, but try a level shifter. + #. SPI only works with 3.3V, most breakouts seem 5V tolerant, but try a level shifter. #. SPI does not like long connections. Try shorter connections. #. SPI does not like prototyping boards. Try soldered connections. #. According to reports #101, #126 and #131, there may be a problem with the soldering on the MFRC522 breakout. You could fix this on your own. -* **Firmware Version: 0x12 = (unknown)** +* **Firmware Version: 0x12 = (unknown) or other random values** - #. The reason of this behaviour is unknown. - #. If this sometimes appear a bad connection or power source is the reason. + #. The exact reason of this behaviour is unknown. + #. Some boards need more time after `PCD_Init()` to be ready. As workaround add a `delay(4)` directly after `PCD_Init()` to give the PCD more time. + #. If this sometimes appears, a bad connection or power source is the reason. #. If the firmware version is reported permanent, it is very likely that the hardware is a fake or has a defect. Contact your supplier. @@ -268,17 +287,28 @@ Troubleshooting #. Newer versions of Mifare cards like DESFire/Ultralight maybe not work according to missing authentication, see `security`_ or different `protocol`_. #. Some boards bought from Chinese manufactures do not use the best components and this can affect the detection of different types of tag/card. In some of these boards, the L1 and L2 inductors do not have a high enough current so the signal generated is not enough to get Ultralight C and NTAG203 tags to work, replacing those with same inductance (2.2uH) but higher operating current inductors should make things work smoothly. Also, in some of those boards the harmonic and matching circuit needs to be tuned, for this replace C4 and C5 with 33pf capacitors and you are all set. (Source: `Mikro Elektronika`_) + * **My mobile phone doesn't recognize the MFRC522** or **my MFRC522 can't read data from other MFRC522** #. Card simulation is not supported. #. Communication with mobile phones is not supported. #. Peer to peer communication is not supported. + * **I can only read the card UID.** #. Maybe the `AccessBits` have been accidentally set and now an unknown password is set. This can not be reverted. #. Probably the card is encrypted. Especially official cards like public transport, university or library cards. There is *no* way to get access with this library. + +* **Where do I get more information?** + + #. For general support from the community, see `Arduino Forum `_ or `StackOverflow `_ . + #. Visit the `community mfrc522 wiki `_ . + #. Read the datasheets! + #. Your preferred search engine. + + * **I need more features.** #. If software: code it and make a pull request. @@ -347,14 +377,14 @@ by Søren Thing Andersen (from http://access.thing.dk). It has been extended with functionality to alter sector 0 on Chinese UID changeable MIFARE card in Oct 2014 by Tom Clement (from http://tomclement.nl). Maintained by miguelbalboa until 2016. -Maintained by Rotzbua from 2016 until 2018. +Maintained by Rotzbua from 2016 until 2022. .. _arduino: https://arduino.cc/ .. _ebay: https://www.ebay.com/ .. _iso/iec 14443a: https://en.wikipedia.org/wiki/ISO/IEC_14443 .. _iso/iec 14443-3\:2011 part 3: -.. _nxp mfrc522: https://www.nxp.com/documents/data_sheet/MFRC522.pdf +.. _nxp mfrc522: https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf .. _broken: https://eprint.iacr.org/2008/166 .. _supported by hardware: https://web.archive.org/web/20151210045625/http://www.nxp.com/documents/leaflet/939775017564.pdf .. _Arduino forum: https://forum.arduino.cc diff --git a/changes.txt b/changes.txt index 6170e8c6..4cc85c95 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,44 @@ -- Add changes to unreleased tag until we make a release. +xxxxx , v1.4.12 + +17 Feb 2025, v1.4.12 +- fix: compiler warning/error @robosphere99 +- chore: add rp2040 to allow list @aaronjamt + +30 Dec 2023, v1.4.11 +- fix: documentation + +1 Nov 2021 , v1.4.10 +- fix: timeout on Non-AVR boards; feat: Use yield() in busy wait loops @greezybacon +- fix PCD problem after selftest + +31 Jul 2021, v1.4.9 +- Removed example AccessControl +- Updated docs + +30 Dec 2020, v1.4.8 +- Fixed wrong SPI clock speed. + +25 Jun 2020, v1.4.7 +- Fixed typos +- Moved PICC memory layout to /doc + +21 Jan 2020, v1.4.6 +- Library in freeze mode, no new features, no new examples, just bugfixes to keep compatibility for old projects +- Updated documentation +- Removed deprecation warnings due code freeze + +12 Jun 2019, v1.4.5 +- Library in freeze mode, no new features, no new examples, just bugfixes to keep compatibility for old projects +- Updated README + +31 Mar 2019, v1.4.4 +- Fixed example +- Fixed UnbrickUidSector +- Updated comments +- Removed teensy from CI and PlatformIO config + 27 Oct 2018, v1.4.3 - Added counterfeit detection and hint about bad boards - Improved hardware based reset @@ -34,7 +73,7 @@ - Added deprecate and compiler warnings @Rotzbua 8 Apr 2017, v1.3.5 -- Updated "AccessControl.ino", bugs fixed and alterate Wipe button polling method without using other library @beyondszine reviewed by @omersiar +- Updated "AccessControl.ino", bugs fixed and alternate wipe button polling method without using other library @beyondszine reviewed by @omersiar - Updated README notice about port for esp8266 @mmmmar 7 Apr 2017, v1.3.4 @@ -143,7 +182,7 @@ 20 Oct 2013 - All constants, functions and parameters are now commented in English. - Code refactored, most function names have changed. -- Support ISO-14443-3 anti collission and 4/7/10 byte UIDs (cascade levels). +- Support ISO-14443-3 anti collision and 4/7/10 byte UIDs (cascade levels). - Added functions for MIFARE Classic Decrement/Increment/Restore/Transfer and MIFARE Ultralight Write. - New examples written. diff --git a/doc/PICCMemoryLayout.md b/doc/PICCMemoryLayout.md new file mode 100644 index 00000000..7b85e36c --- /dev/null +++ b/doc/PICCMemoryLayout.md @@ -0,0 +1,67 @@ +# Memory Layout of common PICCs + +To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has been selected. + +## Datasheet References + +The **MIFARE Classic** chips and protocol is described in the datasheets: + * 1K: https://www.mouser.com/ds/2/302/MF1S503x-89574.pdf + * 4K: https://datasheet.octopart.com/MF1S7035DA4,118-NXP-Semiconductors-datasheet-11046188.pdf + * Mini: http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf + +The **MIFARE Ultralight** chip and protocol is described in the datasheets: + * Ultralight: https://www.nxp.com/docs/en/data-sheet/MF0ICU1.pdf + * Ultralight C: https://www.nxp.com/docs/en/data-sheet/MF0ICU2_SDS_32.pdf + +## MIFARE Classic 1K (MF1S503x) + +Has 16 sectors4 blocks/sector16 bytes/block = 1024 bytes. + + The blocks are numbered 0-63. + Block 3 in each sector is the Sector Trailer. See https://www.mouser.com/ds/2/302/MF1S503x-89574.pdf sections 8.6 and 8.7: + Bytes 0-5: Key A + Bytes 6-8: Access Bits + Bytes 9: User data + Bytes 10-15: Key B (or user data) + Block 0 is read-only manufacturer data. + To access a block, an authentication using a key from the block's sector must be performed first. + Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11). + All keys are set to FFFFFFFFFFFFh at chip delivery. + Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked. + To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns. + +## MIFARE Classic 4K (MF1S703x): + +Has (32 sectors4 blocks/sector + 8 sectors16 blocks/sector)16 bytes/block = 4096 bytes. + + The blocks are numbered 0-255. + The last block in each sector is the Sector Trailer like above. + +## MIFARE Classic Mini (MF1 IC S20): + +Has 5 sectors4 blocks/sector16 bytes/block = 320 bytes. + + The blocks are numbered 0-19. + The last block in each sector is the Sector Trailer like above. + +## MIFARE Ultralight (MF0ICU1): + +Has 16 pages of 4 bytes = 64 bytes. + + Pages 0 + 1 is used for the 7-byte UID. + Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see https://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) + Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. + Pages 4-15 are read/write unless blocked by the lock bytes in page 2. + +## MIFARE Ultralight C (MF0ICU2): + +Has 48 pages of 4 bytes = 192 bytes. + + Pages 0 + 1 is used for the 7-byte UID. + Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see https://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) + Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. + Pages 4-39 are read/write unless blocked by the lock bytes in page 2. + Page 40 Lock bytes + Page 41 16 bit one way counter + Pages 42-43 Authentication configuration + Pages 44-47 Authentication key \ No newline at end of file diff --git a/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz b/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz index 7c98c49d..7642ac20 100644 Binary files a/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz and b/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz differ diff --git a/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png b/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png index 3e5f59d9..e9af1abe 100644 Binary files a/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png and b/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png differ diff --git a/doc/rfidmifare.doc b/doc/rfidmifare.doc index 48fee922..a2f780b1 100644 Binary files a/doc/rfidmifare.doc and b/doc/rfidmifare.doc differ diff --git a/doc/rfidmifare.pdf b/doc/rfidmifare.pdf index 526c71d3..2b85aa68 100644 Binary files a/doc/rfidmifare.pdf and b/doc/rfidmifare.pdf differ diff --git a/examples/AccessControl/AccessControl.ino b/examples/AccessControl/AccessControl.ino deleted file mode 100644 index d0a53875..00000000 --- a/examples/AccessControl/AccessControl.ino +++ /dev/null @@ -1,537 +0,0 @@ -/* - -------------------------------------------------------------------------------------------------------------------- - Example sketch/program showing An Arduino Door Access Control featuring RFID, EEPROM, Relay - -------------------------------------------------------------------------------------------------------------------- - This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid - - This example showing a complete Door Access Control System - - Simple Work Flow (not limited to) : - +---------+ - +----------------------------------->READ TAGS+^------------------------------------------+ - | +--------------------+ | - | | | | - | | | | - | +----v-----+ +-----v----+ | - | |MASTER TAG| |OTHER TAGS| | - | +--+-------+ ++-------------+ | - | | | | | - | | | | | - | +-----v---+ +----v----+ +----v------+ | - | +------------+READ TAGS+---+ |KNOWN TAG| |UNKNOWN TAG| | - | | +-+-------+ | +-----------+ +------------------+ | - | | | | | | | - | +----v-----+ +----v----+ +--v--------+ +-v----------+ +------v----+ | - | |MASTER TAG| |KNOWN TAG| |UNKNOWN TAG| |GRANT ACCESS| |DENY ACCESS| | - | +----------+ +---+-----+ +-----+-----+ +-----+------+ +-----+-----+ | - | | | | | | - | +----+ +----v------+ +--v---+ | +---------------> - +-------+EXIT| |DELETE FROM| |ADD TO| | | - +----+ | EEPROM | |EEPROM| | | - +-----------+ +------+ +-------------------------------+ - - - Use a Master Card which is act as Programmer then you can able to choose card holders who will granted access or not - - * **Easy User Interface** - - Just one RFID tag needed whether Delete or Add Tags. You can choose to use Leds for output or Serial LCD module to inform users. - - * **Stores Information on EEPROM** - - Information stored on non volatile Arduino's EEPROM memory to preserve Users' tag and Master Card. No Information lost - if power lost. EEPROM has unlimited Read cycle but roughly 100,000 limited Write cycle. - - * **Security** - To keep it simple we are going to use Tag's Unique IDs. It's simple and not hacker proof. - - @license Released into the public domain. - - Typical pin layout used: - ----------------------------------------------------------------------------------------- - MFRC522 Arduino Arduino Arduino Arduino Arduino - Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro - Signal Pin Pin Pin Pin Pin Pin - ----------------------------------------------------------------------------------------- - RST/Reset RST 9 5 D9 RESET/ICSP-5 RST - SPI SS SDA(SS) 10 53 D10 10 10 - SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 - SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 - SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 -*/ - -#include // We are going to read and write PICC's UIDs from/to EEPROM -#include // RC522 Module uses SPI protocol -#include // Library for Mifare RC522 Devices - -/* - Instead of a Relay you may want to use a servo. Servos can lock and unlock door locks too - Relay will be used by default -*/ - -// #include - -/* - For visualizing whats going on hardware we need some leds and to control door lock a relay and a wipe button - (or some other hardware) Used common anode led,digitalWriting HIGH turns OFF led Mind that if you are going - to use common cathode led or just seperate leds, simply comment out #define COMMON_ANODE, -*/ - -#define COMMON_ANODE - -#ifdef COMMON_ANODE -#define LED_ON LOW -#define LED_OFF HIGH -#else -#define LED_ON HIGH -#define LED_OFF LOW -#endif - -#define redLed 7 // Set Led Pins -#define greenLed 6 -#define blueLed 5 - -#define relay 4 // Set Relay Pin -#define wipeB 3 // Button pin for WipeMode - -bool programMode = false; // initialize programming mode to false - -uint8_t successRead; // Variable integer to keep if we have Successful Read from Reader - -byte storedCard[4]; // Stores an ID read from EEPROM -byte readCard[4]; // Stores scanned ID read from RFID Module -byte masterCard[4]; // Stores master card's ID read from EEPROM - -// Create MFRC522 instance. -#define SS_PIN 10 -#define RST_PIN 9 -MFRC522 mfrc522(SS_PIN, RST_PIN); - -///////////////////////////////////////// Setup /////////////////////////////////// -void setup() { - //Arduino Pin Configuration - pinMode(redLed, OUTPUT); - pinMode(greenLed, OUTPUT); - pinMode(blueLed, OUTPUT); - pinMode(wipeB, INPUT_PULLUP); // Enable pin's pull up resistor - pinMode(relay, OUTPUT); - //Be careful how relay circuit behave on while resetting or power-cycling your Arduino - digitalWrite(relay, HIGH); // Make sure door is locked - digitalWrite(redLed, LED_OFF); // Make sure led is off - digitalWrite(greenLed, LED_OFF); // Make sure led is off - digitalWrite(blueLed, LED_OFF); // Make sure led is off - - //Protocol Configuration - Serial.begin(9600); // Initialize serial communications with PC - SPI.begin(); // MFRC522 Hardware uses SPI protocol - mfrc522.PCD_Init(); // Initialize MFRC522 Hardware - - //If you set Antenna Gain to Max it will increase reading distance - //mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); - - Serial.println(F("Access Control Example v0.1")); // For debugging purposes - ShowReaderDetails(); // Show details of PCD - MFRC522 Card Reader details - - //Wipe Code - If the Button (wipeB) Pressed while setup run (powered on) it wipes EEPROM - if (digitalRead(wipeB) == LOW) { // when button pressed pin should get low, button connected to ground - digitalWrite(redLed, LED_ON); // Red Led stays on to inform user we are going to wipe - Serial.println(F("Wipe Button Pressed")); - Serial.println(F("You have 10 seconds to Cancel")); - Serial.println(F("This will be remove all records and cannot be undone")); - bool buttonState = monitorWipeButton(10000); // Give user enough time to cancel operation - if (buttonState == true && digitalRead(wipeB) == LOW) { // If button still be pressed, wipe EEPROM - Serial.println(F("Starting Wiping EEPROM")); - for (uint16_t x = 0; x < EEPROM.length(); x = x + 1) { //Loop end of EEPROM address - if (EEPROM.read(x) == 0) { //If EEPROM address 0 - // do nothing, already clear, go to the next address in order to save time and reduce writes to EEPROM - } - else { - EEPROM.write(x, 0); // if not write 0 to clear, it takes 3.3mS - } - } - Serial.println(F("EEPROM Successfully Wiped")); - digitalWrite(redLed, LED_OFF); // visualize a successful wipe - delay(200); - digitalWrite(redLed, LED_ON); - delay(200); - digitalWrite(redLed, LED_OFF); - delay(200); - digitalWrite(redLed, LED_ON); - delay(200); - digitalWrite(redLed, LED_OFF); - } - else { - Serial.println(F("Wiping Cancelled")); // Show some feedback that the wipe button did not pressed for 15 seconds - digitalWrite(redLed, LED_OFF); - } - } - // Check if master card defined, if not let user choose a master card - // This also useful to just redefine the Master Card - // You can keep other EEPROM records just write other than 143 to EEPROM address 1 - // EEPROM address 1 should hold magical number which is '143' - if (EEPROM.read(1) != 143) { - Serial.println(F("No Master Card Defined")); - Serial.println(F("Scan A PICC to Define as Master Card")); - do { - successRead = getID(); // sets successRead to 1 when we get read from reader otherwise 0 - digitalWrite(blueLed, LED_ON); // Visualize Master Card need to be defined - delay(200); - digitalWrite(blueLed, LED_OFF); - delay(200); - } - while (!successRead); // Program will not go further while you not get a successful read - for ( uint8_t j = 0; j < 4; j++ ) { // Loop 4 times - EEPROM.write( 2 + j, readCard[j] ); // Write scanned PICC's UID to EEPROM, start from address 3 - } - EEPROM.write(1, 143); // Write to EEPROM we defined Master Card. - Serial.println(F("Master Card Defined")); - } - Serial.println(F("-------------------")); - Serial.println(F("Master Card's UID")); - for ( uint8_t i = 0; i < 4; i++ ) { // Read Master Card's UID from EEPROM - masterCard[i] = EEPROM.read(2 + i); // Write it to masterCard - Serial.print(masterCard[i], HEX); - } - Serial.println(""); - Serial.println(F("-------------------")); - Serial.println(F("Everything is ready")); - Serial.println(F("Waiting PICCs to be scanned")); - cycleLeds(); // Everything ready lets give user some feedback by cycling leds -} - - -///////////////////////////////////////// Main Loop /////////////////////////////////// -void loop () { - do { - successRead = getID(); // sets successRead to 1 when we get read from reader otherwise 0 - // When device is in use if wipe button pressed for 10 seconds initialize Master Card wiping - if (digitalRead(wipeB) == LOW) { // Check if button is pressed - // Visualize normal operation is iterrupted by pressing wipe button Red is like more Warning to user - digitalWrite(redLed, LED_ON); // Make sure led is off - digitalWrite(greenLed, LED_OFF); // Make sure led is off - digitalWrite(blueLed, LED_OFF); // Make sure led is off - // Give some feedback - Serial.println(F("Wipe Button Pressed")); - Serial.println(F("Master Card will be Erased! in 10 seconds")); - bool buttonState = monitorWipeButton(10000); // Give user enough time to cancel operation - if (buttonState == true && digitalRead(wipeB) == LOW) { // If button still be pressed, wipe EEPROM - EEPROM.write(1, 0); // Reset Magic Number. - Serial.println(F("Master Card Erased from device")); - Serial.println(F("Please reset to re-program Master Card")); - while (1); - } - Serial.println(F("Master Card Erase Cancelled")); - } - if (programMode) { - cycleLeds(); // Program Mode cycles through Red Green Blue waiting to read a new card - } - else { - normalModeOn(); // Normal mode, blue Power LED is on, all others are off - } - } - while (!successRead); //the program will not go further while you are not getting a successful read - if (programMode) { - if ( isMaster(readCard) ) { //When in program mode check First If master card scanned again to exit program mode - Serial.println(F("Master Card Scanned")); - Serial.println(F("Exiting Program Mode")); - Serial.println(F("-----------------------------")); - programMode = false; - return; - } - else { - if ( findID(readCard) ) { // If scanned card is known delete it - Serial.println(F("I know this PICC, removing...")); - deleteID(readCard); - Serial.println("-----------------------------"); - Serial.println(F("Scan a PICC to ADD or REMOVE to EEPROM")); - } - else { // If scanned card is not known add it - Serial.println(F("I do not know this PICC, adding...")); - writeID(readCard); - Serial.println(F("-----------------------------")); - Serial.println(F("Scan a PICC to ADD or REMOVE to EEPROM")); - } - } - } - else { - if ( isMaster(readCard)) { // If scanned card's ID matches Master Card's ID - enter program mode - programMode = true; - Serial.println(F("Hello Master - Entered Program Mode")); - uint8_t count = EEPROM.read(0); // Read the first Byte of EEPROM that - Serial.print(F("I have ")); // stores the number of ID's in EEPROM - Serial.print(count); - Serial.print(F(" record(s) on EEPROM")); - Serial.println(""); - Serial.println(F("Scan a PICC to ADD or REMOVE to EEPROM")); - Serial.println(F("Scan Master Card again to Exit Program Mode")); - Serial.println(F("-----------------------------")); - } - else { - if ( findID(readCard) ) { // If not, see if the card is in the EEPROM - Serial.println(F("Welcome, You shall pass")); - granted(300); // Open the door lock for 300 ms - } - else { // If not, show that the ID was not valid - Serial.println(F("You shall not pass")); - denied(); - } - } - } -} - -///////////////////////////////////////// Access Granted /////////////////////////////////// -void granted ( uint16_t setDelay) { - digitalWrite(blueLed, LED_OFF); // Turn off blue LED - digitalWrite(redLed, LED_OFF); // Turn off red LED - digitalWrite(greenLed, LED_ON); // Turn on green LED - digitalWrite(relay, LOW); // Unlock door! - delay(setDelay); // Hold door lock open for given seconds - digitalWrite(relay, HIGH); // Relock door - delay(1000); // Hold green LED on for a second -} - -///////////////////////////////////////// Access Denied /////////////////////////////////// -void denied() { - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - digitalWrite(redLed, LED_ON); // Turn on red LED - delay(1000); -} - - -///////////////////////////////////////// Get PICC's UID /////////////////////////////////// -uint8_t getID() { - // Getting ready for Reading PICCs - if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue - return 0; - } - if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue - return 0; - } - // There are Mifare PICCs which have 4 byte or 7 byte UID care if you use 7 byte PICC - // I think we should assume every PICC as they have 4 byte UID - // Until we support 7 byte PICCs - Serial.println(F("Scanned PICC's UID:")); - for ( uint8_t i = 0; i < 4; i++) { // - readCard[i] = mfrc522.uid.uidByte[i]; - Serial.print(readCard[i], HEX); - } - Serial.println(""); - mfrc522.PICC_HaltA(); // Stop reading - return 1; -} - -void ShowReaderDetails() { - // Get the MFRC522 software version - byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); - Serial.print(F("MFRC522 Software Version: 0x")); - Serial.print(v, HEX); - if (v == 0x91) - Serial.print(F(" = v1.0")); - else if (v == 0x92) - Serial.print(F(" = v2.0")); - else - Serial.print(F(" (unknown),probably a chinese clone?")); - Serial.println(""); - // When 0x00 or 0xFF is returned, communication probably failed - if ((v == 0x00) || (v == 0xFF)) { - Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?")); - Serial.println(F("SYSTEM HALTED: Check connections.")); - // Visualize system is halted - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - digitalWrite(redLed, LED_ON); // Turn on red LED - while (true); // do not go further - } -} - -///////////////////////////////////////// Cycle Leds (Program Mode) /////////////////////////////////// -void cycleLeds() { - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - digitalWrite(greenLed, LED_ON); // Make sure green LED is on - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - delay(200); - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - digitalWrite(blueLed, LED_ON); // Make sure blue LED is on - delay(200); - digitalWrite(redLed, LED_ON); // Make sure red LED is on - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - delay(200); -} - -//////////////////////////////////////// Normal Mode Led /////////////////////////////////// -void normalModeOn () { - digitalWrite(blueLed, LED_ON); // Blue LED ON and ready to read card - digitalWrite(redLed, LED_OFF); // Make sure Red LED is off - digitalWrite(greenLed, LED_OFF); // Make sure Green LED is off - digitalWrite(relay, HIGH); // Make sure Door is Locked -} - -//////////////////////////////////////// Read an ID from EEPROM ////////////////////////////// -void readID( uint8_t number ) { - uint8_t start = (number * 4 ) + 2; // Figure out starting position - for ( uint8_t i = 0; i < 4; i++ ) { // Loop 4 times to get the 4 Bytes - storedCard[i] = EEPROM.read(start + i); // Assign values read from EEPROM to array - } -} - -///////////////////////////////////////// Add ID to EEPROM /////////////////////////////////// -void writeID( byte a[] ) { - if ( !findID( a ) ) { // Before we write to the EEPROM, check to see if we have seen this card before! - uint8_t num = EEPROM.read(0); // Get the numer of used spaces, position 0 stores the number of ID cards - uint8_t start = ( num * 4 ) + 6; // Figure out where the next slot starts - num++; // Increment the counter by one - EEPROM.write( 0, num ); // Write the new count to the counter - for ( uint8_t j = 0; j < 4; j++ ) { // Loop 4 times - EEPROM.write( start + j, a[j] ); // Write the array values to EEPROM in the right position - } - successWrite(); - Serial.println(F("Succesfully added ID record to EEPROM")); - } - else { - failedWrite(); - Serial.println(F("Failed! There is something wrong with ID or bad EEPROM")); - } -} - -///////////////////////////////////////// Remove ID from EEPROM /////////////////////////////////// -void deleteID( byte a[] ) { - if ( !findID( a ) ) { // Before we delete from the EEPROM, check to see if we have this card! - failedWrite(); // If not - Serial.println(F("Failed! There is something wrong with ID or bad EEPROM")); - } - else { - uint8_t num = EEPROM.read(0); // Get the numer of used spaces, position 0 stores the number of ID cards - uint8_t slot; // Figure out the slot number of the card - uint8_t start; // = ( num * 4 ) + 6; // Figure out where the next slot starts - uint8_t looping; // The number of times the loop repeats - uint8_t j; - uint8_t count = EEPROM.read(0); // Read the first Byte of EEPROM that stores number of cards - slot = findIDSLOT( a ); // Figure out the slot number of the card to delete - start = (slot * 4) + 2; - looping = ((num - slot) * 4); - num--; // Decrement the counter by one - EEPROM.write( 0, num ); // Write the new count to the counter - for ( j = 0; j < looping; j++ ) { // Loop the card shift times - EEPROM.write( start + j, EEPROM.read(start + 4 + j)); // Shift the array values to 4 places earlier in the EEPROM - } - for ( uint8_t k = 0; k < 4; k++ ) { // Shifting loop - EEPROM.write( start + j + k, 0); - } - successDelete(); - Serial.println(F("Succesfully removed ID record from EEPROM")); - } -} - -///////////////////////////////////////// Check Bytes /////////////////////////////////// -bool checkTwo ( byte a[], byte b[] ) { - for ( uint8_t k = 0; k < 4; k++ ) { // Loop 4 times - if ( a[k] != b[k] ) { // IF a != b then false, because: one fails, all fail - return false; - } - } - return true; -} - -///////////////////////////////////////// Find Slot /////////////////////////////////// -uint8_t findIDSLOT( byte find[] ) { - uint8_t count = EEPROM.read(0); // Read the first Byte of EEPROM that - for ( uint8_t i = 1; i <= count; i++ ) { // Loop once for each EEPROM entry - readID(i); // Read an ID from EEPROM, it is stored in storedCard[4] - if ( checkTwo( find, storedCard ) ) { // Check to see if the storedCard read from EEPROM - // is the same as the find[] ID card passed - return i; // The slot number of the card - } - } -} - -///////////////////////////////////////// Find ID From EEPROM /////////////////////////////////// -bool findID( byte find[] ) { - uint8_t count = EEPROM.read(0); // Read the first Byte of EEPROM that - for ( uint8_t i = 1; i < count; i++ ) { // Loop once for each EEPROM entry - readID(i); // Read an ID from EEPROM, it is stored in storedCard[4] - if ( checkTwo( find, storedCard ) ) { // Check to see if the storedCard read from EEPROM - return true; - } - else { // If not, return false - } - } - return false; -} - -///////////////////////////////////////// Write Success to EEPROM /////////////////////////////////// -// Flashes the green LED 3 times to indicate a successful write to EEPROM -void successWrite() { - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - digitalWrite(greenLed, LED_OFF); // Make sure green LED is on - delay(200); - digitalWrite(greenLed, LED_ON); // Make sure green LED is on - delay(200); - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - delay(200); - digitalWrite(greenLed, LED_ON); // Make sure green LED is on - delay(200); - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - delay(200); - digitalWrite(greenLed, LED_ON); // Make sure green LED is on - delay(200); -} - -///////////////////////////////////////// Write Failed to EEPROM /////////////////////////////////// -// Flashes the red LED 3 times to indicate a failed write to EEPROM -void failedWrite() { - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - delay(200); - digitalWrite(redLed, LED_ON); // Make sure red LED is on - delay(200); - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - delay(200); - digitalWrite(redLed, LED_ON); // Make sure red LED is on - delay(200); - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - delay(200); - digitalWrite(redLed, LED_ON); // Make sure red LED is on - delay(200); -} - -///////////////////////////////////////// Success Remove UID From EEPROM /////////////////////////////////// -// Flashes the blue LED 3 times to indicate a success delete to EEPROM -void successDelete() { - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - digitalWrite(redLed, LED_OFF); // Make sure red LED is off - digitalWrite(greenLed, LED_OFF); // Make sure green LED is off - delay(200); - digitalWrite(blueLed, LED_ON); // Make sure blue LED is on - delay(200); - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - delay(200); - digitalWrite(blueLed, LED_ON); // Make sure blue LED is on - delay(200); - digitalWrite(blueLed, LED_OFF); // Make sure blue LED is off - delay(200); - digitalWrite(blueLed, LED_ON); // Make sure blue LED is on - delay(200); -} - -////////////////////// Check readCard IF is masterCard /////////////////////////////////// -// Check to see if the ID passed is the master programing card -bool isMaster( byte test[] ) { - return checkTwo(test, masterCard); -} - -bool monitorWipeButton(uint32_t interval) { - uint32_t now = (uint32_t)millis(); - while ((uint32_t)millis() - now < interval) { - // check on every half a second - if (((uint32_t)millis() % 500) == 0) { - if (digitalRead(wipeB) != LOW) - return false; - } - } - return true; -} diff --git a/examples/ChangeUID/ChangeUID.ino b/examples/ChangeUID/ChangeUID.ino index 19315cd6..82c56657 100644 --- a/examples/ChangeUID/ChangeUID.ino +++ b/examples/ChangeUID/ChangeUID.ino @@ -5,7 +5,6 @@ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid * * This sample shows how to set the UID on a UID changeable MIFARE card. - * NOTE: for more informations read the README.rst * * @author Tom Clement * @license Released into the public domain. @@ -21,6 +20,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include @@ -34,19 +35,12 @@ MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance /* Set your new UID here! */ #define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF} -MFRC522::MIFARE_Key key; - void setup() { Serial.begin(9600); // Initialize serial communications with the PC while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4) SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card Serial.println(F("Warning: this example overwrites the UID of your UID changeable card, use with care!")); - - // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory. - for (byte i = 0; i < 6; i++) { - key.keyByte[i] = 0xFF; - } } // Setting the UID can be as simple as this: @@ -61,7 +55,7 @@ void setup() { // But of course this is a more proper approach void loop() { - // Look for new cards, and select one if present + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. And if present, select one. if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) { delay(50); return; diff --git a/examples/DumpInfo/DumpInfo.ino b/examples/DumpInfo/DumpInfo.ino index 5cb0aaa8..1a799e09 100644 --- a/examples/DumpInfo/DumpInfo.ino +++ b/examples/DumpInfo/DumpInfo.ino @@ -31,6 +31,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include @@ -46,12 +48,13 @@ void setup() { while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4) SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 + delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks...")); } void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } diff --git a/examples/FixBrickedUID/FixBrickedUID.ino b/examples/FixBrickedUID/FixBrickedUID.ino index 391a2521..d1f36544 100644 --- a/examples/FixBrickedUID/FixBrickedUID.ino +++ b/examples/FixBrickedUID/FixBrickedUID.ino @@ -20,6 +20,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include @@ -30,19 +32,12 @@ MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance -MFRC522::MIFARE_Key key; - void setup() { Serial.begin(9600); // Initialize serial communications with the PC while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4) SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card Serial.println(F("Warning: this example clears your mifare UID, use with care!")); - - // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory. - for (byte i = 0; i < 6; i++) { - key.keyByte[i] = 0xFF; - } } void loop() { diff --git a/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino b/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino index 1d788326..21359b0e 100644 --- a/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino +++ b/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino @@ -25,6 +25,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout * */ @@ -65,7 +67,7 @@ void setup() { * Main loop. */ void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) return; diff --git a/examples/MinimalInterrupt/MinimalInterrupt.ino b/examples/MinimalInterrupt/MinimalInterrupt.ino index 281569c8..23273cf2 100644 --- a/examples/MinimalInterrupt/MinimalInterrupt.ino +++ b/examples/MinimalInterrupt/MinimalInterrupt.ino @@ -23,6 +23,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout * */ @@ -35,8 +37,6 @@ MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance. -MFRC522::MIFARE_Key key; - volatile bool bNewInt = false; byte regVal = 0x7F; void activateRec(MFRC522 mfrc522); diff --git a/examples/Ntag216_AUTH/Ntag216_AUTH.ino b/examples/Ntag216_AUTH/Ntag216_AUTH.ino index fc9f22c9..b2f3905a 100644 --- a/examples/Ntag216_AUTH/Ntag216_AUTH.ino +++ b/examples/Ntag216_AUTH/Ntag216_AUTH.ino @@ -1,13 +1,17 @@ -//This example show how you can get Authenticated by the NTAG213,215,216 by default the tags are unprotected in order to protect them we need to write 4 different values: -// Using mfrc522.MIFARE_Ultralight_Write(PageNum, Data, #Databytes)) -//1.- we need to write the 32bit passWord to page 0xE5 !for ntag 213 and 215 page is different refer to nxp documentation! -//2.- Now Write the 16 bits pACK to the page 0xE6 use the 2 high bytes like this: pACKH + pACKL + 00 + 00 after an authentication the tag will return this secret bytes -//3.- Now we need to write the first page we want to protect this is a 1 byte data in page 0xE3 we need to write 00 + 00 + 00 + firstPage all pages after this one are write protected -// Now WRITE protection is ACTIVATED so we need to get authenticated in order to write the last data -//4.- Finally we need to write an access record in order to READ protect the card this step is optional only if you want to read protect also write 80 + 00 + 00 + 00 to 0xE4 -//After completeing all these steps you will nee to authentiate first in order to read or write ant page after the first page you selected to protect -//To disengage proection just write the page (0xE3) to 00 + 00 + 00 + FF that going to remove all protection -//Made by GARGANTUA from RoboCreators.com & paradoxalabs.com +/* + * This example show how you can get Authenticated by the NTAG213,215,216. By default the tags are unprotected in order to protect them we need to write 4 different values: + * Using mfrc522.MIFARE_Ultralight_Write(PageNum, Data, #Databytes)) + * 1.- We need to write the 32bit passWord to page 0xE5 !for ntag 213 and 215 page is different refer to nxp documentation! + * 2.- Now Write the 16 bits pACK to the page 0xE6 use the 2 high bytes like this: pACKH + pACKL + 00 + 00 after an authentication the tag will return this secret bytes + * 3.- Now we need to write the first page we want to protect this is a 1 byte data in page 0xE3 we need to write 00 + 00 + 00 + firstPage all pages after this one are write protected + * Now WRITE protection is ACTIVATED so we need to get authenticated in order to write the last data + * 4.- Finally we need to write an access record in order to READ protect the card this step is optional only if you want to read protect also write 80 + 00 + 00 + 00 to 0xE4 + * After completing all these steps you will nee to authenticate first in order to read or write ant page after the first page you selected to protect. + * To disengage protection just write the page (0xE3) to 00 + 00 + 00 + FF that going to remove all protection. + * + * @author GARGANTUA from RoboCreators.com & paradoxalabs.com + * @license Released into the public domain. + */ #include #include @@ -26,7 +30,7 @@ void setup() { } void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } @@ -36,11 +40,11 @@ void loop() { return; } - byte PSWBuff[] = {0xFF, 0xFF, 0xFF, 0xFF}; //32 bit PassWord default FFFFFFFF - byte pACK[] = {0, 0}; //16 bit PassWord ACK returned by the NFCtag + byte PSWBuff[] = {0xFF, 0xFF, 0xFF, 0xFF}; // 32 bit password default FFFFFFFF. + byte pACK[] = {0, 0}; // 16 bit password ACK returned by the NFCtag. Serial.print("Auth: "); - Serial.println(mfrc522.PCD_NTAG216_AUTH(&PSWBuff[0], pACK)); //Request Authentification if return STATUS_OK we are good + Serial.println(mfrc522.PCD_NTAG216_AUTH(&PSWBuff[0], pACK)); // Request authentification if return STATUS_OK we are good. //Print PassWordACK Serial.print(pACK[0], HEX); @@ -50,9 +54,9 @@ void loop() { byte RBuff[18]; //Serial.print("CHG BLK: "); - //Serial.println(mfrc522.MIFARE_Ultralight_Write(0xE3, WBuff, 4)); //How to write to a page + //Serial.println(mfrc522.MIFARE_Ultralight_Write(0xE3, WBuff, 4)); // How to write to a page. - mfrc522.PICC_DumpMifareUltralightToSerial(); //This is a modifier dunp just cghange the for cicle to < 232 instead of < 16 in order to see all the pages on NTAG216 + mfrc522.PICC_DumpMifareUltralightToSerial(); // This is a modifier dump just change the for circle to < 232 instead of < 16 in order to see all the pages on NTAG216. delay(3000); -} \ No newline at end of file +} diff --git a/examples/RFID-Cloner/RFID-Cloner.ino b/examples/RFID-Cloner/RFID-Cloner.ino index 9b9e8bd7..2a0986a4 100644 --- a/examples/RFID-Cloner/RFID-Cloner.ino +++ b/examples/RFID-Cloner/RFID-Cloner.ino @@ -1,6 +1,6 @@ /* * Copy the RFID card data into variables and then - * scan the second empty card to copy all the date + * scan the second empty card to copy all the data * ---------------------------------------------------------------------------- * Example sketch/program which will try the most used default keys listed in * https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys to dump the @@ -18,6 +18,8 @@ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout + * */ #include diff --git a/examples/ReadAndWrite/ReadAndWrite.ino b/examples/ReadAndWrite/ReadAndWrite.ino index af951602..ab05e688 100644 --- a/examples/ReadAndWrite/ReadAndWrite.ino +++ b/examples/ReadAndWrite/ReadAndWrite.ino @@ -25,6 +25,8 @@ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout + * */ #include @@ -64,7 +66,7 @@ void setup() { * Main loop. */ void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) return; diff --git a/examples/ReadNUID/ReadNUID.ino b/examples/ReadNUID/ReadNUID.ino index 9ff99da3..8e7fd0ed 100644 --- a/examples/ReadNUID/ReadNUID.ino +++ b/examples/ReadNUID/ReadNUID.ino @@ -26,6 +26,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include @@ -36,8 +38,6 @@ MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class -MFRC522::MIFARE_Key key; - // Init array that will store new NUID byte nuidPICC[4]; @@ -46,18 +46,12 @@ void setup() { SPI.begin(); // Init SPI bus rfid.PCD_Init(); // Init MFRC522 - for (byte i = 0; i < 6; i++) { - key.keyByte[i] = 0xFF; - } - Serial.println(F("This code scan the MIFARE Classsic NUID.")); - Serial.print(F("Using the following key:")); - printHex(key.keyByte, MFRC522::MF_KEY_SIZE); } void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! rfid.PICC_IsNewCardPresent()) return; @@ -121,7 +115,7 @@ void printHex(byte *buffer, byte bufferSize) { */ void printDec(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { - Serial.print(buffer[i] < 0x10 ? " 0" : " "); + Serial.print(' '); Serial.print(buffer[i], DEC); } } diff --git a/examples/ReadUidMultiReader/ReadUidMultiReader.ino b/examples/ReadUidMultiReader/ReadUidMultiReader.ino index c14c17a5..348a3748 100644 --- a/examples/ReadUidMultiReader/ReadUidMultiReader.ino +++ b/examples/ReadUidMultiReader/ReadUidMultiReader.ino @@ -25,14 +25,16 @@ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout + * */ #include #include #define RST_PIN 9 // Configurable, see typical pin layout above -#define SS_1_PIN 10 // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2 -#define SS_2_PIN 8 // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1 +#define SS_1_PIN 10 // Configurable, take a unused pin, only HIGH/LOW required, must be different to SS 2 +#define SS_2_PIN 8 // Configurable, take a unused pin, only HIGH/LOW required, must be different to SS 1 #define NR_OF_READERS 2 diff --git a/examples/firmware_check/firmware_check.ino b/examples/firmware_check/firmware_check.ino index 943ce5b1..2213f3b0 100644 --- a/examples/firmware_check/firmware_check.ino +++ b/examples/firmware_check/firmware_check.ino @@ -6,7 +6,6 @@ * * This example test the firmware of your MFRC522 reader module, only known version can be checked. If the test passed * it do not mean that your module is faultless! Some modules have bad or broken antennas or the PICC is broken. - * NOTE: for more informations read the README.rst * * @author Rotzbua * @license Released into the public domain. @@ -22,6 +21,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include diff --git a/examples/rfid_default_keys/rfid_default_keys.ino b/examples/rfid_default_keys/rfid_default_keys.ino index 8f3ea560..13bce31b 100644 --- a/examples/rfid_default_keys/rfid_default_keys.ino +++ b/examples/rfid_default_keys/rfid_default_keys.ino @@ -23,6 +23,8 @@ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout + * */ #include @@ -81,12 +83,7 @@ bool try_key(MFRC522::MIFARE_Key *key) byte buffer[18]; byte block = 0; MFRC522::StatusCode status; - - // http://arduino.stackexchange.com/a/14316 - if ( ! mfrc522.PICC_IsNewCardPresent()) - return false; - if ( ! mfrc522.PICC_ReadCardSerial()) - return false; + // Serial.println(F("Authenticating using key A...")); status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { @@ -124,7 +121,7 @@ bool try_key(MFRC522::MIFARE_Key *key) * Main loop. */ void loop() { - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) return; @@ -153,5 +150,11 @@ void loop() { // no need to try other keys for this PICC break; } + + // http://arduino.stackexchange.com/a/14316 + if ( ! mfrc522.PICC_IsNewCardPresent()) + break; + if ( ! mfrc522.PICC_ReadCardSerial()) + break; } } diff --git a/examples/rfid_read_personal_data/rfid_read_personal_data.ino b/examples/rfid_read_personal_data/rfid_read_personal_data.ino index 5271cd11..993eda51 100644 --- a/examples/rfid_read_personal_data/rfid_read_personal_data.ino +++ b/examples/rfid_read_personal_data/rfid_read_personal_data.ino @@ -17,6 +17,8 @@ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 + * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout */ #include @@ -49,7 +51,7 @@ void loop() { //------------------------------------------- - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } diff --git a/examples/rfid_write_personal_data/rfid_write_personal_data.ino b/examples/rfid_write_personal_data/rfid_write_personal_data.ino index 75bb2fb8..fa74670a 100644 --- a/examples/rfid_write_personal_data/rfid_write_personal_data.ino +++ b/examples/rfid_write_personal_data/rfid_write_personal_data.ino @@ -12,6 +12,8 @@ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 * + * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout + * * Hardware required: * Arduino * PCD (Proximity Coupling Device): NXP MFRC522 Contactless Reader IC @@ -40,7 +42,7 @@ void loop() { MFRC522::MIFARE_Key key; for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; - // Look for new cards + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } @@ -153,4 +155,4 @@ void loop() { mfrc522.PICC_HaltA(); // Halt PICC mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD -} \ No newline at end of file +} diff --git a/library.json b/library.json index b00fc683..478cdc30 100644 --- a/library.json +++ b/library.json @@ -1,14 +1,15 @@ { "name": "MFRC522", + "version": "1.4.12", + "license": "Unlicense", "keywords": "rfid, spi", - "description": "Read a card using a MFRC522 reader on your SPI interface", + "description": "Arduino RFID Library for MFRC522 (SPI). Read/Write a RFID Card or Tag using the ISO/IEC 14443A/MIFARE interface.", "repository": { "type": "git", "url": "https://github.com/miguelbalboa/rfid.git" }, - "version": "1.4.3", "exclude": "doc", "frameworks": "arduino", - "platforms": ["atmelavr", "ststm32", "teensy", "espressif8266","samd"] + "platforms": ["atmelavr", "atmelsam", "ststm32", "espressif8266", "espressif32", "samd", "rp2040"] } diff --git a/library.properties b/library.properties index 142afb60..ebf4fd7a 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=MFRC522 -version=1.4.3 +version=1.4.12 author=GithubCommunity maintainer=GithubCommunity sentence=Arduino RFID Library for MFRC522 (SPI) paragraph=Read/Write a RFID Card or Tag using the ISO/IEC 14443A/MIFARE interface. category=Communication url=https://github.com/miguelbalboa/rfid -architectures=avr,STM32F1,teensy,esp8266,samd +architectures=avr,megaavr,STM32F1,teensy,esp8266,esp32,samd,atmelsam,rp2040 diff --git a/src/MFRC522.cpp b/src/MFRC522.cpp index 90575d57..7da85c1c 100644 --- a/src/MFRC522.cpp +++ b/src/MFRC522.cpp @@ -163,11 +163,13 @@ MFRC522::StatusCode MFRC522::PCD_CalculateCRC( byte *data, ///< In: Pointer to PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO PCD_WriteRegister(CommandReg, PCD_CalcCRC); // Start the calculation - // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73μs. - // TODO check/modify for other architectures than Arduino Uno 16bit + // Wait for the CRC calculation to complete. Check for the register to + // indicate that the CRC calculation is complete in a loop. If the + // calculation is not indicated as complete in ~90ms, then time out + // the operation. + const uint32_t deadline = millis() + 89; - // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us. - for (uint16_t i = 5000; i > 0; i--) { + do { // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved byte n = PCD_ReadRegister(DivIrqReg); if (n & 0x04) { // CRCIRq bit set - calculation done @@ -177,8 +179,11 @@ MFRC522::StatusCode MFRC522::PCD_CalculateCRC( byte *data, ///< In: Pointer to result[1] = PCD_ReadRegister(CRCResultRegH); return STATUS_OK; } + yield(); } - // 89ms passed and nothing happend. Communication with the MFRC522 might be down. + while (static_cast (millis()) < deadline); + + // 89ms passed and nothing happened. Communication with the MFRC522 might be down. return STATUS_TIMEOUT; } // End PCD_CalculateCRC() @@ -204,7 +209,7 @@ void MFRC522::PCD_Init() { if (digitalRead(_resetPowerDownPin) == LOW) { // The MFRC522 chip is in power down mode. pinMode(_resetPowerDownPin, OUTPUT); // Now set the resetPowerDownPin as digital output. - digitalWrite(_resetPowerDownPin, LOW); // Make shure we have a clean LOW state. + digitalWrite(_resetPowerDownPin, LOW); // Make sure we have a clean LOW state. delayMicroseconds(2); // 8.8.1 Reset timing requirements says about 100ns. Let us be generous: 2μsl digitalWrite(_resetPowerDownPin, HIGH); // Exit power down mode. This triggers a hard reset. // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74μs. Let us be generous: 50ms. @@ -392,6 +397,11 @@ bool MFRC522::PCD_PerformSelfTest() { } } + // 8. Perform a re-init, because PCD does not work after test. + // Reset does not work as expected. + // "Auto self-test done" does not work as expected. + PCD_Init(); + // Test passed; all is good. return true; } // End PCD_PerformSelfTest() @@ -422,6 +432,7 @@ void MFRC522::PCD_SoftPowerUp(){ if(!(val & (1<<4))){ // if powerdown bit is 0 break;// wake up procedure is finished } + yield(); } } @@ -477,22 +488,32 @@ MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC( byte command, ///< The co PCD_SetRegisterBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts } - // Wait for the command to complete. - // In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting. - // Each iteration of the do-while-loop takes 17.86μs. - // TODO check/modify for other architectures than Arduino Uno 16bit - uint16_t i; - for (i = 2000; i > 0; i--) { + // In PCD_Init() we set the TAuto flag in TModeReg. This means the timer + // automatically starts when the PCD stops transmitting. + // + // Wait here for the command to complete. The bits specified in the + // `waitIRq` parameter define what bits constitute a completed command. + // When they are set in the ComIrqReg register, then the command is + // considered complete. If the command is not indicated as complete in + // ~36ms, then consider the command as timed out. + const uint32_t deadline = millis() + 36; + bool completed = false; + + do { byte n = PCD_ReadRegister(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq if (n & waitIRq) { // One of the interrupts that signal success has been set. + completed = true; break; } if (n & 0x01) { // Timer interrupt - nothing received in 25ms return STATUS_TIMEOUT; } + yield(); } - // 35.7ms and nothing happend. Communication with the MFRC522 might be down. - if (i == 0) { + while (static_cast (millis()) < deadline); + + // 36ms and nothing happened. Communication with the MFRC522 might be down. + if (!completed) { return STATUS_TIMEOUT; } @@ -1281,7 +1302,7 @@ const __FlashStringHelper *MFRC522::GetStatusCodeName(MFRC522::StatusCode code / switch (code) { case STATUS_OK: return F("Success."); case STATUS_ERROR: return F("Error in communication."); - case STATUS_COLLISION: return F("Collission detected."); + case STATUS_COLLISION: return F("Collision detected."); case STATUS_TIMEOUT: return F("Timeout in communication."); case STATUS_NO_ROOM: return F("A buffer is not big enough."); case STATUS_INTERNAL_ERROR: return F("Internal error in the code. Should not happen."); @@ -1369,8 +1390,6 @@ void MFRC522::PCD_DumpVersionToSerial() { * Dumps debug info about the selected PICC to Serial. * On success the PICC is halted after dumping the data. * For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried. - * - * @DEPRECATED Kept for bakward compatibility */ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned from a successful PICC_Select(). ) { @@ -1416,8 +1435,6 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro /** * Dumps card info (UID,SAK,Type) about the selected PICC to Serial. - * - * @DEPRECATED kept for backward compatibility */ void MFRC522::PICC_DumpDetailsToSerial(Uid *uid ///< Pointer to Uid struct returned from a successful PICC_Select(). ) { @@ -1721,7 +1738,7 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { byte validBits = 7; /* Our command is only 7 bits. After receiving card response, this will contain amount of valid response bits. */ byte response[32]; // Card's response is written here - byte received; + byte received = sizeof(response); MFRC522::StatusCode status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 40 if(status != STATUS_OK) { if(logErrors) { diff --git a/src/MFRC522.h b/src/MFRC522.h index b2030514..597c4a5d 100644 --- a/src/MFRC522.h +++ b/src/MFRC522.h @@ -1,76 +1,11 @@ /** - * MFRC522.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT. - * Based on code Dr.Leong ( WWW.B2CQSHOP.COM ) - * Created by Miguel Balboa (circuitito.com), Jan, 2012. - * Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.) - * Extended by Tom Clement with functionality to write to sector 0 of UID changeable Mifare cards. - * Released into the public domain. + * Library to use Arduino MFRC522 module. * - * Please read this file for an overview and then MFRC522.cpp for comments on the specific functions. - * Search for "mf-rc522" on ebay.com to purchase the MF-RC522 board. - * - * There are three hardware components involved: - * 1) The micro controller: An Arduino - * 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless Reader IC - * 3) The PICC (short for Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203. - * - * The microcontroller and card reader uses SPI for communication. - * The protocol is described in the MFRC522 datasheet: http://www.nxp.com/documents/data_sheet/MFRC522.pdf - * - * The card reader and the tags communicate using a 13.56MHz electromagnetic field. - * The protocol is defined in ISO/IEC 14443-3 Identification cards -- Contactless integrated circuit cards -- Proximity cards -- Part 3: Initialization and anticollision". - * A free version of the final draft can be found at http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf - * Details are found in chapter 6, Type A – Initialization and anticollision. + * @authors Dr.Leong, Miguel Balboa, Søren Thing Andersen, Tom Clement, many more! See GitLog. * - * If only the PICC UID is wanted, the above documents has all the needed information. - * To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has been selected. - * The MIFARE Classic chips and protocol is described in the datasheets: - * 1K: http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf - * 4K: http://datasheet.octopart.com/MF1S7035DA4,118-NXP-Semiconductors-datasheet-11046188.pdf - * Mini: http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf - * The MIFARE Ultralight chip and protocol is described in the datasheets: - * Ultralight: http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf - * Ultralight C: http://www.nxp.com/documents/short_data_sheet/MF0ICU2_SDS.pdf + * For more information read the README. * - * MIFARE Classic 1K (MF1S503x): - * Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes. - * The blocks are numbered 0-63. - * Block 3 in each sector is the Sector Trailer. See http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf sections 8.6 and 8.7: - * Bytes 0-5: Key A - * Bytes 6-8: Access Bits - * Bytes 9: User data - * Bytes 10-15: Key B (or user data) - * Block 0 is read-only manufacturer data. - * To access a block, an authentication using a key from the block's sector must be performed first. - * Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11). - * All keys are set to FFFFFFFFFFFFh at chip delivery. - * Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked. - * To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns. - * MIFARE Classic 4K (MF1S703x): - * Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes. - * The blocks are numbered 0-255. - * The last block in each sector is the Sector Trailer like above. - * MIFARE Classic Mini (MF1 IC S20): - * Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes. - * The blocks are numbered 0-19. - * The last block in each sector is the Sector Trailer like above. - * - * MIFARE Ultralight (MF0ICU1): - * Has 16 pages of 4 bytes = 64 bytes. - * Pages 0 + 1 is used for the 7-byte UID. - * Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) - * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. - * Pages 4-15 are read/write unless blocked by the lock bytes in page 2. - * MIFARE Ultralight C (MF0ICU2): - * Has 48 pages of 4 bytes = 192 bytes. - * Pages 0 + 1 is used for the 7-byte UID. - * Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) - * Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. - * Pages 4-39 are read/write unless blocked by the lock bytes in page 2. - * Page 40 Lock bytes - * Page 41 16 bit one way counter - * Pages 42-43 Authentication configuration - * Pages 44-47 Authentication key + * Please read this file for an overview and then MFRC522.cpp for comments on the specific functions. */ #ifndef MFRC522_h #define MFRC522_h @@ -83,7 +18,9 @@ #include #include -#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz +#ifndef MFRC522_SPICLOCK +#define MFRC522_SPICLOCK (4000000u) // MFRC522 accept upto 10MHz, set to 4MHz. +#endif // Firmware data for self-test // Reference values based on firmware version @@ -333,7 +270,6 @@ class MFRC522 { // Functions for setting up the Arduino ///////////////////////////////////////////////////////////////////////////////////// MFRC522(); - DEPRECATED_MSG("use MFRC522(byte chipSelectPin, byte resetPowerDownPin)") MFRC522(byte resetPowerDownPin); MFRC522(byte chipSelectPin, byte resetPowerDownPin); @@ -352,7 +288,6 @@ class MFRC522 { // Functions for manipulating the MFRC522 ///////////////////////////////////////////////////////////////////////////////////// void PCD_Init(); - DEPRECATED_MSG("use PCD_Init(byte chipSelectPin, byte resetPowerDownPin)") void PCD_Init(byte resetPowerDownPin); void PCD_Init(byte chipSelectPin, byte resetPowerDownPin); void PCD_Reset(); @@ -416,13 +351,9 @@ class MFRC522 { void PICC_DumpMifareUltralightToSerial(); // Advanced functions for MIFARE - DEPRECATED_MSG("name will change in next version") void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3); - DEPRECATED_MSG("will move to extra class in next version") bool MIFARE_OpenUidBackdoor(bool logErrors); - DEPRECATED_MSG("will move to extra class in next version") bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors); - DEPRECATED_MSG("will move to extra class in next version") bool MIFARE_UnbrickUidSector(bool logErrors); ///////////////////////////////////////////////////////////////////////////////////// diff --git a/src/MFRC522Extended.cpp b/src/MFRC522Extended.cpp index da603ab7..5ab783bc 100644 --- a/src/MFRC522Extended.cpp +++ b/src/MFRC522Extended.cpp @@ -821,7 +821,7 @@ MFRC522::StatusCode MFRC522Extended::TCL_Transceive(TagInfo *tag, byte *sendData // Swap block number on success tag->blockNumber = !tag->blockNumber; - if (backData && (backLen > 0)) { + if (backData && (*backLen > 0)) { if (*backLen < in.inf.size) return STATUS_NO_ROOM; @@ -844,7 +844,7 @@ MFRC522::StatusCode MFRC522Extended::TCL_Transceive(TagInfo *tag, byte *sendData if (result != STATUS_OK) return result; - if (backData && (backLen > 0)) { + if (backData && (*backLen > 0)) { if ((*backLen + ackDataSize) > totalBackLen) return STATUS_NO_ROOM;