瀏覽代碼

添加nfc读写ndef格式库

chenzixuan 2 月之前
父節點
當前提交
92e52349a5
共有 66 個文件被更改,包括 9216 次插入3 次删除
  1. 392 0
      arduinoLibrary/rc522/MFRC522/README.rst
  2. 24 0
      arduinoLibrary/rc522/MFRC522/UNLICENSE
  3. 203 0
      arduinoLibrary/rc522/MFRC522/changes.txt
  4. 67 0
      arduinoLibrary/rc522/MFRC522/doc/PICCMemoryLayout.md
  5. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz
  6. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png
  7. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522 - Pin Layout.png
  8. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v2.fzpz
  9. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v2.png
  10. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v3.fzpz
  11. 二進制
      arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v3.png
  12. 二進制
      arduinoLibrary/rc522/MFRC522/doc/rfidmifare.doc
  13. 二進制
      arduinoLibrary/rc522/MFRC522/doc/rfidmifare.pdf
  14. 105 0
      arduinoLibrary/rc522/MFRC522/examples/ChangeUID/ChangeUID.ino
  15. 69 0
      arduinoLibrary/rc522/MFRC522/examples/DumpInfo/DumpInfo.ino
  16. 48 0
      arduinoLibrary/rc522/MFRC522/examples/FixBrickedUID/FixBrickedUID.ino
  17. 321 0
      arduinoLibrary/rc522/MFRC522/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino
  18. 137 0
      arduinoLibrary/rc522/MFRC522/examples/MinimalInterrupt/MinimalInterrupt.ino
  19. 62 0
      arduinoLibrary/rc522/MFRC522/examples/Ntag216_AUTH/Ntag216_AUTH.ino
  20. 314 0
      arduinoLibrary/rc522/MFRC522/examples/RFID-Cloner/RFID-Cloner.ino
  21. 202 0
      arduinoLibrary/rc522/MFRC522/examples/ReadAndWrite/ReadAndWrite.ino
  22. 121 0
      arduinoLibrary/rc522/MFRC522/examples/ReadNUID/ReadNUID.ino
  23. 99 0
      arduinoLibrary/rc522/MFRC522/examples/ReadUidMultiReader/ReadUidMultiReader.ino
  24. 63 0
      arduinoLibrary/rc522/MFRC522/examples/firmware_check/firmware_check.ino
  25. 160 0
      arduinoLibrary/rc522/MFRC522/examples/rfid_default_keys/rfid_default_keys.ino
  26. 140 0
      arduinoLibrary/rc522/MFRC522/examples/rfid_read_personal_data/rfid_read_personal_data.ino
  27. 158 0
      arduinoLibrary/rc522/MFRC522/examples/rfid_write_personal_data/rfid_write_personal_data.ino
  28. 223 0
      arduinoLibrary/rc522/MFRC522/keywords.txt
  29. 15 0
      arduinoLibrary/rc522/MFRC522/library.json
  30. 9 0
      arduinoLibrary/rc522/MFRC522/library.properties
  31. 1950 0
      arduinoLibrary/rc522/MFRC522/src/MFRC522.cpp
  32. 371 0
      arduinoLibrary/rc522/MFRC522/src/MFRC522.h
  33. 1160 0
      arduinoLibrary/rc522/MFRC522/src/MFRC522Extended.cpp
  34. 120 0
      arduinoLibrary/rc522/MFRC522/src/MFRC522Extended.h
  35. 20 0
      arduinoLibrary/rc522/MFRC522/src/deprecated.h
  36. 12 0
      arduinoLibrary/rc522/MFRC522/src/require_cpp11.h
  37. 29 0
      arduinoLibrary/rc522/NDEF_MFRC522/LICENSE
  38. 111 0
      arduinoLibrary/rc522/NDEF_MFRC522/README.md
  39. 35 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/CleanTag/CleanTag.ino
  40. 33 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/EraseTag/EraseTag.ino
  41. 35 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/FormatTag/FormatTag.ino
  42. 30 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/ReadTag/ReadTag.ino
  43. 80 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/ReadTagExtended/ReadTagExtended.ino
  44. 35 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/WriteTag/WriteTag.ino
  45. 37 0
      arduinoLibrary/rc522/NDEF_MFRC522/examples/WriteTagMultipleRecords/WriteTagMultipleRecords.ino
  46. 61 0
      arduinoLibrary/rc522/NDEF_MFRC522/keywords.txt
  47. 32 0
      arduinoLibrary/rc522/NDEF_MFRC522/library.json
  48. 11 0
      arduinoLibrary/rc522/NDEF_MFRC522/library.properties
  49. 25 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/Due.h
  50. 456 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/MifareClassic.cpp
  51. 37 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/MifareClassic.h
  52. 258 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/MifareUltralight.cpp
  53. 34 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/MifareUltralight.h
  54. 59 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/Ndef.cpp
  55. 19 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/Ndef.h
  56. 277 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NdefMessage.cpp
  57. 42 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NdefMessage.h
  58. 328 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NdefRecord.cpp
  59. 52 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NdefRecord.h
  60. 203 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NfcAdapter.cpp
  61. 35 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NfcAdapter.h
  62. 123 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NfcTag.cpp
  63. 41 0
      arduinoLibrary/rc522/NDEF_MFRC522/src/NfcTag.h
  64. 6 3
      bledome/bledome.ino
  65. 127 0
      bledome/ndef.h
  66. 二進制
      扫码枪文档.doc

File diff suppressed because it is too large
+ 392 - 0
arduinoLibrary/rc522/MFRC522/README.rst


+ 24 - 0
arduinoLibrary/rc522/MFRC522/UNLICENSE

@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <https://unlicense.org/>

+ 203 - 0
arduinoLibrary/rc522/MFRC522/changes.txt

@@ -0,0 +1,203 @@
+-- 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
+
+04 Oct 2018, v1.4.2
+- Fixed keywords
+- Changed development status of library
+
+04 Oct 2018, v1.4.1
+- Replaced UINT8_MAX by UNUSED_PIN
+- Replaced default value NULL for pointer with correct nullptr
+- Added pin layout for wemos d1 mini @mmone
+- Added alternative fritzing layout for mfrc522 reader @jose1711
+- Added soft power control functions @Bill2462
+- Fixed typo in example ReadAndWrite.ino @Drachenfrucht1
+- Fixed grammar @KiddieD
+- Fixed infinite loop in example AccessControl.ino @mads256c 
+- Fixed 0-index key ID equals to 0 fails in AccessControl.ino @thoaitrieu
+- Changed type boolean to bool for a more common use @Rotzbua 
+- Fixed wrong var names in PICC_Select MFRC522.cpp @tuyethoa08041997
+- Fixed hang PCD_Init() on non-arduino boards @heziegl
+- Fixed possible infinite loop PCD_Reset() @psgreco
+- And many thanks to all other contributors
+
+13 Apr 2018, v1.4.0
+- Replaced UINT8_MAX by UNUSED_PIN @Rotzbua
+- Fixed hang PCD_Init() on non-arduino boards @heziegl
+- deprecate MIFARE_SetAccessBits @Rotzbua
+- IMPORTANT: v1.4.X will be last version under license "unlicense"
+
+22 Mar 2017, v1.3.6
+- Added deprecate and compiler warnings @Rotzbua
+
+8 Apr 2017, v1.3.5
+- 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
+- Added new example "rfid_read_personal_data.ino" @ryand1011
+- Updated example "rfid_write_personal_data.ino" code style to Arduino IDE @Rotzbua
+- Removed (temp.) Teensy from travis build script because fails @Rotzbua
+
+26 Mar 2017, v1.3.3
+- Fixed bugs in MFRC522Extended, now should work with Desfire.h from JPG-Consulting @Rotzbua
+- Fixed UINT8_MAX error @Rotzbua
+
+15 Mar 2017, v1.3.2
+- Added ESP8266 to library.properties
+
+15 Mar 2017, v1.3.1
+- Fixed compiler warning in MFRC522Extended @Rotzbua
+- Removed unused function @Rotzbua
+
+13 Mar 2017, v1.3.0
+- Warning: Source has moved to folder src!
+- Added addtional class to support ISO/IEC 14443-4 PICCs @JPG-Consulting
+- Added RATS (Request for Answer To Select) @JPG-Consulting
+- More information see https://github.com/miguelbalboa/rfid/pull/271 @JPG-Consulting
+
+13 Mar 2017, v1.2.1
+- Removed need for reset pin #275 @tkoester
+- Added SPI speed option + Various minor changes #276 @tuyethoa08041997
+- Updated documentation, travis build script and small code change @Rotzbua
+
+3 Jan 2017, v1.2.0
+- Warning: This version introduce usage of stdint.h, usage of not well defined int types are abandoned.
+           Interface has changed: e.g. long -> int32_t
+           @Rotzbua
+- Removed problematic example examples/servo_motor/servo_motor.ino @omersiar
+- Added examples/AccessControl/AccessControl.ino @omersiar
+- Fixed minor issues reported in #211 @omersiar
+- Added bad components hint to README @danielcbit
+- Fixed selftest @surr
+- Fixed auth problem with long UIDs @surr
+
+26 Aug 2016, v1.1.9
+- Warning: Only Arduino IDE version 1.6 is supported, please update your IDE to 1.6 to use this Library.
+- Added ESP8266 platform support @Rotzbua
+- Changed README.rst content to show more info @Rotzbua
+- Minor Changes to examples/ReadUidMultiReader/ReadUidMultiReader.ino example @Rotzbua
+
+11 Feb 2016, v1.1.8
+- Added examples/MinimalInterrupt/MinimalInterrupt.ino example, Interrupt example @lmmeng
+- Added .gitignore file allows the project to be more easily used as a subproject. @BenWiederhake
+- Added Added Teensy 2.0 & Tensy++ 2.0 pinouts to README.rst @jkutianski
+
+16 Jan 2016, v1.1.7
+- README.rst Spelling and Grammar Tweak @cuthbertnibbles
+- Added examples/servo_motor/servo_motor.ino example, Arduino RFID Access Control with a Servo Motor @techied
+- Added examples/RFID-Cloner/RFID-Cloner.ino Copy from rfid cards with standard authentication @stefanblommaert
+- Fix compile error at examples/RFID-Cloner/RFID-Cloner.ino, using MFRC522:::PICC_Type, @Rotzbua
+
+06 Jan 2016, v1.1.6
+- Fixed compilation error for examples/ReadNUID/ReadNUID.ino example. @Rotzbua
+
+04 Jan 2016, v1.1.5
+- Use settings functions on SPI libraries, setSPIConfig was deleted, now the library use SPI.beginTransaction() and SPI.endTransaction() @sophiekovalevsky
+- Added examples/ReadNUID/ReadNUID.ino example, showing how to read new NUID from a PICC to serial. @sophiekovalevsky
+
+03 Jan 2016, v1.1.4
+- Added Authentication with Ntag 213,215,216 returns the pACK MFRC522::PCD_NTAG216_AUTH @Gargantuanman
+- Starting to use versions http://semver.org/
+- Continuous Integration @ivankravets 
+- functions return MFRC522::StatusCode and MFRC522::PICC_Type instead of generic byte @rotzbua
+- removed int-values of MFRC522::StatusCode and MFRC522::PICC_Type @rotzbua
+
+05 Dec 2015
+- recognize infineon cards correctly @mayatforest
+- added multi reader support, see example @lmmeng
+
+10 Nov 2014
+- Updated the changelog.
+- Added makefile.
+
+24 Oct 2014
+- Added PlatformIO-based manifest file.
+
+17 Jul 2014
+- Written documentation for the library.
+- Added rfid_default_keys example.
+
+11 Jun 2014
+- Updated example: ReadAndWrite.
+
+14 Apr 2014
+- Updated examples: DumpInfo, MifareClassicValueBlock, and ReadAndWrite.
+
+12 Feb 2014
+- Fixed resetPowerDownPin initial state.
+
+29 Jan 2014
+- Fixed chipSelectPin initial state.
+
+30 Nov 2013
+- Examples put in their own folders.
+- Updated the keywords.txt file.
+
+12 Nov 2013
+- Updated examples: DumpInfo, MifareClassicValueBlock, and ReadAndWrite.
+
+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 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.
+
+19 Oct 2013
+- Renamed library from RFID to MFRC522 (RFID seemed to generic).
+- Register names changed to comply with datasheet.
+- Global defines moved into class.
+
+24 Sep 2013
+- Turn off encryption when tag is halted.
+
+27 Jan 2013
+- Added README and small TODO list.
+- Added example to show Serial on LCD display.
+
+09 Sep 2012
+- Initial commit to GitHub.

+ 67 - 0
arduinoLibrary/rc522/MFRC522/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 

二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.fzz


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/Arduino-Uno-r3-with-RFID-RC522.png


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522 - Pin Layout.png


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v2.fzpz


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v2.png


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v3.fzpz


二進制
arduinoLibrary/rc522/MFRC522/doc/fritzing/RFID-RC522-v3.png


二進制
arduinoLibrary/rc522/MFRC522/doc/rfidmifare.doc


二進制
arduinoLibrary/rc522/MFRC522/doc/rfidmifare.pdf


+ 105 - 0
arduinoLibrary/rc522/MFRC522/examples/ChangeUID/ChangeUID.ino

@@ -0,0 +1,105 @@
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example to change UID of changeable MIFARE card.
+ * --------------------------------------------------------------------------------------------------------------------
+ * 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.
+ * 
+ * @author Tom Clement
+ * @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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN   9     // Configurable, see typical pin layout above
+#define SS_PIN    10    // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
+
+/* Set your new UID here! */
+#define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF}
+
+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!"));
+}
+
+// Setting the UID can be as simple as this:
+//void loop() {
+//  byte newUid[] = NEW_UID;
+//  if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
+//    Serial.println("Wrote new UID to card.");
+//  }
+//  delay(1000);
+//}
+
+// But of course this is a more proper approach
+void loop() {
+  
+  // 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;
+  }
+  
+  // Now a card is selected. The UID and SAK is in mfrc522.uid.
+  
+  // Dump UID
+  Serial.print(F("Card UID:"));
+  for (byte i = 0; i < mfrc522.uid.size; i++) {
+    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
+    Serial.print(mfrc522.uid.uidByte[i], HEX);
+  } 
+  Serial.println();
+
+  // Dump PICC type
+//  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+//  Serial.print(F("PICC type: "));
+//  Serial.print(mfrc522.PICC_GetTypeName(piccType));
+//  Serial.print(F(" (SAK "));
+//  Serial.print(mfrc522.uid.sak);
+//  Serial.print(")\r\n");
+//  if (  piccType != MFRC522::PICC_TYPE_MIFARE_MINI 
+//    &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
+//    &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
+//    Serial.println(F("This sample only works with MIFARE Classic cards."));
+//    return;
+//  }
+  
+  // Set new UID
+  byte newUid[] = NEW_UID;
+  if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
+    Serial.println(F("Wrote new UID to card."));
+  }
+  
+  // Halt PICC and re-select it so DumpToSerial doesn't get confused
+  mfrc522.PICC_HaltA();
+  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
+    return;
+  }
+  
+  // Dump the new memory contents
+  Serial.println(F("New UID and contents:"));
+  mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
+  
+  delay(2000);
+}

+ 69 - 0
arduinoLibrary/rc522/MFRC522/examples/DumpInfo/DumpInfo.ino

@@ -0,0 +1,69 @@
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example sketch/program showing how to read data from a PICC to serial.
+ * --------------------------------------------------------------------------------------------------------------------
+ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
+ * 
+ * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
+ * Reader on the Arduino SPI interface.
+ * 
+ * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
+ * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
+ * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
+ * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
+ * when removing the PICC from reading distance too early.
+ * 
+ * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
+ * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
+ * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
+ * keep the PICCs at reading distance until complete.
+ * 
+ * @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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9          // Configurable, see typical pin layout above
+#define SS_PIN          10         // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
+
+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
+	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() {
+	// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+	if ( ! mfrc522.PICC_IsNewCardPresent()) {
+		return;
+	}
+
+	// Select one of the cards
+	if ( ! mfrc522.PICC_ReadCardSerial()) {
+		return;
+	}
+
+	// Dump debug info about the card; PICC_HaltA() is automatically called
+	mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
+}

+ 48 - 0
arduinoLibrary/rc522/MFRC522/examples/FixBrickedUID/FixBrickedUID.ino

@@ -0,0 +1,48 @@
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example sketch/program to fix a broken UID changeable MIFARE cards.
+ * --------------------------------------------------------------------------------------------------------------------
+ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
+ * 
+ * This sample shows how to fix a broken UID changeable MIFARE cards that have a corrupted sector 0.
+ * 
+ * @author Tom Clement
+ * @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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN   9     // Configurable, see typical pin layout above
+#define SS_PIN    10    // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
+
+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!"));
+}
+
+void loop() {
+  if ( mfrc522.MIFARE_UnbrickUidSector(false) ) {
+    Serial.println(F("Cleared sector 0, set UID to 1234. Card should be responsive again now."));
+  }
+  delay(1000);
+}

+ 321 - 0
arduinoLibrary/rc522/MFRC522/examples/MifareClassicValueBlock/MifareClassicValueBlock.ino

@@ -0,0 +1,321 @@
+/**
+ * ----------------------------------------------------------------------------
+ * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
+ * for further details and other examples.
+ * 
+ * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
+ * 
+ * Released into the public domain.
+ * ----------------------------------------------------------------------------
+ * This sample shows how to setup blocks on a MIFARE Classic PICC (= card/tag)
+ * to be in "Value Block" mode: in this mode the operations Increment/Decrement,
+ * Restore and Transfer can be used.
+ * 
+ * BEWARE: Data will be written to the PICC, in sector #1 (blocks #4 to #7).
+ * 
+ * 
+ * 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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ * 
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+
+MFRC522::MIFARE_Key key;
+
+/**
+ * Initialize.
+ */
+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
+
+    // Prepare the key (used both as key A and as key B)
+    // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
+    for (byte i = 0; i < 6; i++) {
+        key.keyByte[i] = 0xFF;
+    }
+
+    Serial.println(F("Scan a MIFARE Classic PICC to demonstrate Value Block mode."));
+    Serial.print(F("Using key (for A and B):"));
+    dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
+    Serial.println();
+    
+    Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
+}
+
+/**
+ * Main loop.
+ */
+void loop() {
+    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+    if ( ! mfrc522.PICC_IsNewCardPresent())
+        return;
+
+    // Select one of the cards
+    if ( ! mfrc522.PICC_ReadCardSerial())
+        return;
+
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+    Serial.print(F("PICC type: "));
+    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+    Serial.println(mfrc522.PICC_GetTypeName(piccType));
+
+    // Check for compatibility
+    if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
+        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
+        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
+        Serial.println(F("This sample only works with MIFARE Classic cards."));
+        return;
+    }
+
+    // In this sample we use the second sector,
+    // that is: sector #1, covering block #4 up to and including block #7
+    byte sector         = 1;
+    byte valueBlockA    = 5;
+    byte valueBlockB    = 6;
+    byte trailerBlock   = 7;
+    MFRC522::StatusCode status;
+    byte buffer[18];
+    byte size = sizeof(buffer);
+    int32_t value;
+
+    // Authenticate using key A
+    Serial.println(F("Authenticating using key A..."));
+    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+
+    // Show the whole sector as it currently is
+    Serial.println(F("Current data in sector:"));
+    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
+    Serial.println();
+    
+    // We need a sector trailer that defines blocks 5 and 6 as Value Blocks and enables key B
+    // The last block in a sector (block #3 for Mifare Classic 1K) is the Sector Trailer.
+    // See http://www.nxp.com/documents/data_sheet/MF1S503x.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)
+    byte trailerBuffer[] = {
+        255, 255, 255, 255, 255, 255,       // Keep default key A
+        0, 0, 0,
+        0,
+        255, 255, 255, 255, 255, 255};      // Keep default key B
+    // The access bits are stored in a peculiar fashion.
+    // There are four groups:
+    //      g[0]    Access bits for block 0 (for sectors 0-31)
+    //              or blocks 0-4 (for sectors 32-39)
+    //      g[1]    Access bits for block 1 (for sectors 0-31)
+    //              or blocks 5-9 (for sectors 32-39)
+    //      g[2]    Access bits for block 2 (for sectors 0-31)
+    //              or blocks 10-14 (for sectors 32-39)
+    //      g[3]    Access bits for the Sector Trailer: block 3 (for sectors 0-31)
+    //              or block 15 (for sectors 32-39)
+    // Each group has access bits [C1 C2 C3], in this code C1 is MSB and C3 is LSB.
+    // Determine the bit pattern needed using MIFARE_SetAccessBits:
+    //      g0=0    access bits for block 0 (of this sector) using [0 0 0] = 000b = 0
+    //              which means key A|B have r/w for block 0 of this sector
+    //              which (in this example) translates to block #4 within sector #1;
+    //              this is the transport configuration (at factory delivery).
+    //      g1=6    access bits for block 1 (of this sector) using [1 1 0] = 110b = 6
+    //              which means block 1 (of this sector) is used as a value block,
+    //              which (in this example) translates to block #5 within sector #1;
+    //              where key A|B have r, key B has w, key B can increment,
+    //              and key A|B can decrement, transfer, and restore.
+    //      g2=6    same thing for block 2 (of this sector): set it to a value block;
+    //              which (in this example) translates to block #6 within sector #1;
+    //      g3=3    access bits for block 3 (of this sector): the Sector Trailer here;
+    //              using [0 1 1] = 011b = 3 which means only key B has r/w access
+    //              to the Sector Trailer (block 3 of this sector) from now on
+    //              which (in this example) translates to block #7 within sector #1;
+    mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);
+
+    // Read the sector trailer as it is currently stored on the PICC
+    Serial.println(F("Reading sector trailer..."));
+    status = mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Read() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    // Check if it matches the desired access pattern already;
+    // because if it does, we don't need to write it again...
+    if (    buffer[6] != trailerBuffer[6]
+        ||  buffer[7] != trailerBuffer[7]
+        ||  buffer[8] != trailerBuffer[8]) {
+        // They don't match (yet), so write it to the PICC
+        Serial.println(F("Writing new sector trailer..."));
+        status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16);
+        if (status != MFRC522::STATUS_OK) {
+            Serial.print(F("MIFARE_Write() failed: "));
+            Serial.println(mfrc522.GetStatusCodeName(status));
+            return;
+        }
+    }
+
+    // Authenticate using key B
+    Serial.println(F("Authenticating again using key B..."));
+    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+
+    // A value block has a 32 bit signed value stored three times
+    // and an 8 bit address stored 4 times. Make sure that valueBlockA
+    // and valueBlockB have that format (note that it will only format
+    // the block when it doesn't comply to the expected format already).
+    formatValueBlock(valueBlockA);
+    formatValueBlock(valueBlockB);
+
+    // Add 1 to the value of valueBlockA and store the result in valueBlockA.
+    Serial.print("Adding 1 to value of block "); Serial.println(valueBlockA);
+    status = mfrc522.MIFARE_Increment(valueBlockA, 1);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Increment() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    status = mfrc522.MIFARE_Transfer(valueBlockA);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Transfer() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    // Show the new value of valueBlockA
+    status = mfrc522.MIFARE_GetValue(valueBlockA, &value);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("mifare_GetValue() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    Serial.print("New value of value block "); Serial.print(valueBlockA);
+    Serial.print(" = "); Serial.println(value);
+
+    // Decrement 10 from the value of valueBlockB and store the result in valueBlockB.
+    Serial.print("Subtracting 10 from value of block "); Serial.println(valueBlockB);
+    status = mfrc522.MIFARE_Decrement(valueBlockB, 10);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Decrement() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    status = mfrc522.MIFARE_Transfer(valueBlockB);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Transfer() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    // Show the new value of valueBlockB
+    status = mfrc522.MIFARE_GetValue(valueBlockB, &value);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("mifare_GetValue() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    Serial.print(F("New value of value block ")); Serial.print(valueBlockB);
+    Serial.print(F(" = ")); Serial.println(value);
+    // Check some boundary...
+    if (value <= -100) {
+        Serial.println(F("Below -100, so resetting it to 255 = 0xFF just for fun..."));
+        status = mfrc522.MIFARE_SetValue(valueBlockB, 255);
+        if (status != MFRC522::STATUS_OK) {
+            Serial.print(F("mifare_SetValue() failed: "));
+            Serial.println(mfrc522.GetStatusCodeName(status));
+            return;
+        }
+    }
+
+    // Dump the sector data
+    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
+    Serial.println();
+
+    // Halt PICC
+    mfrc522.PICC_HaltA();
+    // Stop encryption on PCD
+    mfrc522.PCD_StopCrypto1();
+}
+
+/**
+ * Helper routine to dump a byte array as hex values to Serial.
+ */
+void dump_byte_array(byte *buffer, byte bufferSize) {
+    for (byte i = 0; i < bufferSize; i++) {
+        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+        Serial.print(buffer[i], HEX);
+    }
+}
+
+/**
+ * Ensure that a given block is formatted as a Value Block.
+ */
+void formatValueBlock(byte blockAddr) {
+    byte buffer[18];
+    byte size = sizeof(buffer);
+    MFRC522::StatusCode status;
+
+    Serial.print(F("Reading block ")); Serial.println(blockAddr);
+    status = mfrc522.MIFARE_Read(blockAddr, buffer, &size);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Read() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+
+    if (    (buffer[0] == (byte)~buffer[4])
+        &&  (buffer[1] == (byte)~buffer[5])
+        &&  (buffer[2] == (byte)~buffer[6])
+        &&  (buffer[3] == (byte)~buffer[7])
+
+        &&  (buffer[0] == buffer[8])
+        &&  (buffer[1] == buffer[9])
+        &&  (buffer[2] == buffer[10])
+        &&  (buffer[3] == buffer[11])
+
+        &&  (buffer[12] == (byte)~buffer[13])
+        &&  (buffer[12] ==        buffer[14])
+        &&  (buffer[12] == (byte)~buffer[15])) {
+        Serial.println(F("Block has correct Value Block format."));
+    }
+    else {
+        Serial.println(F("Formatting as Value Block..."));
+        byte valueBlock[] = {
+            0, 0, 0, 0,
+            255, 255, 255, 255,
+            0, 0, 0, 0,
+            blockAddr, ~blockAddr, blockAddr, ~blockAddr };
+        status = mfrc522.MIFARE_Write(blockAddr, valueBlock, 16);
+        if (status != MFRC522::STATUS_OK) {
+            Serial.print(F("MIFARE_Write() failed: "));
+            Serial.println(mfrc522.GetStatusCodeName(status));
+        }
+    }
+}

+ 137 - 0
arduinoLibrary/rc522/MFRC522/examples/MinimalInterrupt/MinimalInterrupt.ino

@@ -0,0 +1,137 @@
+/**
+ * ----------------------------------------------------------------------------
+ * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
+ * for further details and other examples.
+ * 
+ * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
+ * 
+ * Released into the public domain.
+ * ----------------------------------------------------------------------------
+ * Minimal example how to use the interrupts to read the UID of a MIFARE Classic PICC
+ * (= card/tag).
+ * 
+ * 
+ * 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        3                10
+ * IRQ         ?            ?             ?         ?          2                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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ * 
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          3           // Configurable, see typical pin layout above
+#define IRQ_PIN         2           // Configurable, depends on hardware
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+
+volatile bool bNewInt = false;
+byte regVal = 0x7F;
+void activateRec(MFRC522 mfrc522);
+void clearInt(MFRC522 mfrc522);
+
+/**
+ * Initialize.
+ */
+void setup() {
+  Serial.begin(115200); // 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
+
+  /* read and printout the MFRC522 version (valid values 0x91 & 0x92)*/
+  Serial.print(F("Ver: 0x"));
+  byte readReg = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
+  Serial.println(readReg, HEX);
+
+  /* setup the IRQ pin*/
+  pinMode(IRQ_PIN, INPUT_PULLUP);
+
+  /*
+   * Allow the ... irq to be propagated to the IRQ pin
+   * For test purposes propagate the IdleIrq and loAlert
+   */
+  regVal = 0xA0; //rx irq
+  mfrc522.PCD_WriteRegister(mfrc522.ComIEnReg, regVal);
+
+  bNewInt = false; //interrupt flag
+
+  /*Activate the interrupt*/
+  attachInterrupt(digitalPinToInterrupt(IRQ_PIN), readCard, FALLING);
+
+  do { //clear a spourious interrupt at start
+    ;
+  } while (!bNewInt);
+  bNewInt = false;
+
+  Serial.println(F("End setup"));
+}
+
+/**
+ * Main loop.
+ */
+void loop() {
+  if (bNewInt) { //new read interrupt
+    Serial.print(F("Interrupt. "));
+    mfrc522.PICC_ReadCardSerial(); //read the tag data
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+
+    clearInt(mfrc522);
+    mfrc522.PICC_HaltA();
+    bNewInt = false;
+  }
+
+  // The receiving block needs regular retriggering (tell the tag it should transmit??)
+  // (mfrc522.PCD_WriteRegister(mfrc522.FIFODataReg,mfrc522.PICC_CMD_REQA);)
+  activateRec(mfrc522);
+  delay(100);
+} //loop()
+
+/**
+ * Helper routine to dump a byte array as hex values to Serial.
+ */
+void dump_byte_array(byte *buffer, byte bufferSize) {
+  for (byte i = 0; i < bufferSize; i++) {
+    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+    Serial.print(buffer[i], HEX);
+  }
+}
+/**
+ * MFRC522 interrupt serving routine
+ */
+void readCard() {
+  bNewInt = true;
+}
+
+/*
+ * The function sending to the MFRC522 the needed commands to activate the reception
+ */
+void activateRec(MFRC522 mfrc522) {
+  mfrc522.PCD_WriteRegister(mfrc522.FIFODataReg, mfrc522.PICC_CMD_REQA);
+  mfrc522.PCD_WriteRegister(mfrc522.CommandReg, mfrc522.PCD_Transceive);
+  mfrc522.PCD_WriteRegister(mfrc522.BitFramingReg, 0x87);
+}
+
+/*
+ * The function to clear the pending interrupt bits after interrupt serving routine
+ */
+void clearInt(MFRC522 mfrc522) {
+  mfrc522.PCD_WriteRegister(mfrc522.ComIrqReg, 0x7F);
+}
+

+ 62 - 0
arduinoLibrary/rc522/MFRC522/examples/Ntag216_AUTH/Ntag216_AUTH.ino

@@ -0,0 +1,62 @@
+/*
+ * 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 <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN    9   // 
+#define SS_PIN    10    //
+
+MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
+
+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
+  Serial.println(F("Scan PICC to see UID, type, and data blocks..."));
+}
+
+void loop() {
+  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+  if ( ! mfrc522.PICC_IsNewCardPresent()) {
+    return;
+  }
+
+  // Select one of the cards
+  if ( ! mfrc522.PICC_ReadCardSerial()) {
+    return;
+  }
+
+  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.
+
+  //Print PassWordACK
+  Serial.print(pACK[0], HEX);
+  Serial.println(pACK[1], HEX);
+
+  byte WBuff[] = {0x00, 0x00, 0x00, 0x04};
+  byte RBuff[18];
+
+  //Serial.print("CHG BLK: ");
+  //Serial.println(mfrc522.MIFARE_Ultralight_Write(0xE3, WBuff, 4));  // How to write to a page.
+
+  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);
+}

+ 314 - 0
arduinoLibrary/rc522/MFRC522/examples/RFID-Cloner/RFID-Cloner.ino

@@ -0,0 +1,314 @@
+/*
+ * Copy the RFID card data into variables and then 
+ * 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
+ * block 0 of a MIFARE RFID card using a RFID-RC522 reader.
+ * 
+ * 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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ *
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+
+byte buffer[18];
+byte block;
+byte waarde[64][16];
+MFRC522::StatusCode status;
+    
+MFRC522::MIFARE_Key key;
+
+// Number of known default keys (hard-coded)
+// NOTE: Synchronize the NR_KNOWN_KEYS define with the defaultKeys[] array
+#define NR_KNOWN_KEYS   8
+// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
+byte knownKeys[NR_KNOWN_KEYS][MFRC522::MF_KEY_SIZE] =  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // FF FF FF FF FF FF = factory default
+    {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}, // A0 A1 A2 A3 A4 A5
+    {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5}, // B0 B1 B2 B3 B4 B5
+    {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd}, // 4D 3A 99 C3 51 DD
+    {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a}, // 1A 98 2C 7E 45 9A
+    {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}, // D3 F7 D3 F7 D3 F7
+    {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, // AA BB CC DD EE FF
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  // 00 00 00 00 00 00
+};
+
+char choice;
+/*
+ * Initialize.
+ */
+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("Try the most used default keys to print block 0 to 63 of a MIFARE PICC."));
+    Serial.println("1.Read card \n2.Write to card \n3.Copy the data.");
+
+    for (byte i = 0; i < 6; i++) {
+        key.keyByte[i] = 0xFF;
+    }
+}
+
+
+
+ //Via seriele monitor de bytes uitlezen in hexadecimaal
+ 
+void dump_byte_array(byte *buffer, byte bufferSize) {
+    for (byte i = 0; i < bufferSize; i++) {
+        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+        Serial.print(buffer[i], HEX);
+    }
+}
+//Via seriele monitor de bytes uitlezen in ASCI
+
+void dump_byte_array1(byte *buffer, byte bufferSize) {
+  for (byte i = 0; i < bufferSize; i++) {
+    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+    Serial.write(buffer[i]);
+  }
+}
+
+/*
+ * Try using the PICC (the tag/card) with the given key to access block 0 to 63.
+ * On success, it will show the key details, and dump the block data on Serial.
+ *
+ * @return true when the given key worked, false otherwise.
+ */
+ 
+bool try_key(MFRC522::MIFARE_Key *key)
+{
+    bool result = false;
+    
+    for(byte block = 0; block < 64; block++){
+      
+    // 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) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return false;
+    }
+
+    // Read block
+    byte byteCount = sizeof(buffer);
+    status = mfrc522.MIFARE_Read(block, buffer, &byteCount);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Read() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+    }
+    else {
+        // Successful read
+        result = true;
+        Serial.print(F("Success with key:"));
+        dump_byte_array((*key).keyByte, MFRC522::MF_KEY_SIZE);
+        Serial.println();
+        
+        // Dump block data
+        Serial.print(F("Block ")); Serial.print(block); Serial.print(F(":"));
+        dump_byte_array1(buffer, 16); //omzetten van hex naar ASCI
+        Serial.println();
+        
+        for (int p = 0; p < 16; p++) //De 16 bits uit de block uitlezen
+        {
+          waarde [block][p] = buffer[p];
+          Serial.print(waarde[block][p]);
+          Serial.print(" ");
+        }
+        
+        }
+    }
+    Serial.println();
+    
+    Serial.println("1.Read card \n2.Write to card \n3.Copy the data.");
+
+    mfrc522.PICC_HaltA();       // Halt PICC
+    mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
+    return result;
+    
+    start();
+}
+
+/*
+ * Main loop.
+ */
+void loop() {
+  start();
+    
+}
+
+void start(){
+  choice = Serial.read();
+  
+  if(choice == '1')
+  {
+    Serial.println("Read the card");
+    keuze1();
+      
+    }
+    else if(choice == '2')
+    {
+      Serial.println("See what is in the variables");
+      keuze2();
+    }
+    else if(choice == '3')
+    {
+      Serial.println("Copying the data on to the new card");
+      keuze3();
+    }
+}
+
+void keuze2(){ //Test waardes in blokken
+  
+  for(block = 4; block <= 62; block++){
+    if(block == 7 || block == 11 || block == 15 || block == 19 || block == 23 || block == 27 || block == 31 || block == 35 || block == 39 || block == 43 || block == 47 || block == 51 || block == 55 || block == 59){
+      block ++;
+    }
+  
+  Serial.print(F("Writing data into block ")); 
+  Serial.print(block);
+  Serial.println("\n");
+  
+    for(int j = 0; j < 16; j++){
+      Serial.print(waarde[block][j]);
+      Serial.print(" ");
+    }
+    Serial.println("\n");
+    
+  }
+  
+  Serial.println("1.Read card \n2.Write to card \n3.Copy the data.");
+  start();
+}
+
+void keuze3(){ //Copy the data in the new card
+Serial.println("Insert new card...");
+  // Look for new cards
+    if ( ! mfrc522.PICC_IsNewCardPresent())
+        return;
+
+    // Select one of the cards
+    if ( ! mfrc522.PICC_ReadCardSerial())
+        return;
+
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+    Serial.print(F("PICC type: "));
+    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+    Serial.println(mfrc522.PICC_GetTypeName(piccType));
+    
+    // Try the known default keys
+    /*MFRC522::MIFARE_Key key;
+    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
+        // Copy the known key into the MIFARE_Key structure
+        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
+            key.keyByte[i] = knownKeys[k][i];
+        }
+    }*/
+    for (byte i = 0; i < 6; i++) {
+        key.keyByte[i] = 0xFF;
+    }
+
+  for(int i = 4; i <= 62; i++){ //De blocken 4 tot 62 kopieren, behalve al deze onderstaande blocken (omdat deze de authenticatie blokken zijn)
+    if(i == 7 || i == 11 || i == 15 || i == 19 || i == 23 || i == 27 || i == 31 || i == 35 || i == 39 || i == 43 || i == 47 || i == 51 || i == 55 || i == 59){
+      i++;
+    }
+    block = i;
+    
+      // Authenticate using key A
+    Serial.println(F("Authenticating using key A..."));
+    status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    
+    // Authenticate using key B
+    Serial.println(F("Authenticating again using key B..."));
+    status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, block, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+    
+    // Write data to the block
+    Serial.print(F("Writing data into block ")); 
+    Serial.print(block);
+    Serial.println("\n");
+          
+    dump_byte_array(waarde[block], 16); 
+    
+          
+     status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(block, waarde[block], 16);
+      if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Write() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+      }
+    
+        
+     Serial.println("\n");
+     
+  }
+  mfrc522.PICC_HaltA();       // Halt PICC
+  mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
+  
+  Serial.println("1.Read card \n2.Write to card \n3.Copy the data.");
+  start();
+}
+
+void keuze1(){ //Read card
+  Serial.println("Insert card...");
+  // Look for new cards
+    if ( ! mfrc522.PICC_IsNewCardPresent())
+        return;
+
+    // Select one of the cards
+    if ( ! mfrc522.PICC_ReadCardSerial())
+        return;
+
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+    Serial.print(F("PICC type: "));
+    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+    Serial.println(mfrc522.PICC_GetTypeName(piccType));
+    
+    // Try the known default keys
+    MFRC522::MIFARE_Key key;
+    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
+        // Copy the known key into the MIFARE_Key structure
+        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
+            key.keyByte[i] = knownKeys[k][i];
+        }
+        // Try the key
+        if (try_key(&key)) {
+            // Found and reported on the key and block,
+            // no need to try other keys for this PICC
+            break;
+        }
+    }
+}

+ 202 - 0
arduinoLibrary/rc522/MFRC522/examples/ReadAndWrite/ReadAndWrite.ino

@@ -0,0 +1,202 @@
+/**
+ * ----------------------------------------------------------------------------
+ * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
+ * for further details and other examples.
+ *
+ * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
+ *
+ * Released into the public domain.
+ * ----------------------------------------------------------------------------
+ * This sample shows how to read and write data blocks on a MIFARE Classic PICC
+ * (= card/tag).
+ *
+ * BEWARE: Data will be written to the PICC, in sector #1 (blocks #4 to #7).
+ *
+ *
+ * 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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ *
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+
+MFRC522::MIFARE_Key key;
+
+/**
+ * Initialize.
+ */
+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
+
+    // Prepare the key (used both as key A and as key B)
+    // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
+    for (byte i = 0; i < 6; i++) {
+        key.keyByte[i] = 0xFF;
+    }
+
+    Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
+    Serial.print(F("Using key (for A and B):"));
+    dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
+    Serial.println();
+
+    Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
+}
+
+/**
+ * Main loop.
+ */
+void loop() {
+    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+    if ( ! mfrc522.PICC_IsNewCardPresent())
+        return;
+
+    // Select one of the cards
+    if ( ! mfrc522.PICC_ReadCardSerial())
+        return;
+
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+    Serial.print(F("PICC type: "));
+    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+    Serial.println(mfrc522.PICC_GetTypeName(piccType));
+
+    // Check for compatibility
+    if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
+        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
+        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
+        Serial.println(F("This sample only works with MIFARE Classic cards."));
+        return;
+    }
+
+    // In this sample we use the second sector,
+    // that is: sector #1, covering block #4 up to and including block #7
+    byte sector         = 1;
+    byte blockAddr      = 4;
+    byte dataBlock[]    = {
+        0x01, 0x02, 0x03, 0x04, //  1,  2,   3,  4,
+        0x05, 0x06, 0x07, 0x08, //  5,  6,   7,  8,
+        0x09, 0x0a, 0xff, 0x0b, //  9, 10, 255, 11,
+        0x0c, 0x0d, 0x0e, 0x0f  // 12, 13, 14, 15
+    };
+    byte trailerBlock   = 7;
+    MFRC522::StatusCode status;
+    byte buffer[18];
+    byte size = sizeof(buffer);
+
+    // Authenticate using key A
+    Serial.println(F("Authenticating using key A..."));
+    status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+
+    // Show the whole sector as it currently is
+    Serial.println(F("Current data in sector:"));
+    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
+    Serial.println();
+
+    // Read data from the block
+    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
+    Serial.println(F(" ..."));
+    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Read() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+    }
+    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
+    dump_byte_array(buffer, 16); Serial.println();
+    Serial.println();
+
+    // Authenticate using key B
+    Serial.println(F("Authenticating again using key B..."));
+    status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("PCD_Authenticate() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+        return;
+    }
+
+    // Write data to the block
+    Serial.print(F("Writing data into block ")); Serial.print(blockAddr);
+    Serial.println(F(" ..."));
+    dump_byte_array(dataBlock, 16); Serial.println();
+    status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Write() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+    }
+    Serial.println();
+
+    // Read data from the block (again, should now be what we have written)
+    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
+    Serial.println(F(" ..."));
+    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
+    if (status != MFRC522::STATUS_OK) {
+        Serial.print(F("MIFARE_Read() failed: "));
+        Serial.println(mfrc522.GetStatusCodeName(status));
+    }
+    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
+    dump_byte_array(buffer, 16); Serial.println();
+
+    // Check that data in block is what we have written
+    // by counting the number of bytes that are equal
+    Serial.println(F("Checking result..."));
+    byte count = 0;
+    for (byte i = 0; i < 16; i++) {
+        // Compare buffer (= what we've read) with dataBlock (= what we've written)
+        if (buffer[i] == dataBlock[i])
+            count++;
+    }
+    Serial.print(F("Number of bytes that match = ")); Serial.println(count);
+    if (count == 16) {
+        Serial.println(F("Success :-)"));
+    } else {
+        Serial.println(F("Failure, no match :-("));
+        Serial.println(F("  perhaps the write didn't work properly..."));
+    }
+    Serial.println();
+
+    // Dump the sector data
+    Serial.println(F("Current data in sector:"));
+    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
+    Serial.println();
+
+    // Halt PICC
+    mfrc522.PICC_HaltA();
+    // Stop encryption on PCD
+    mfrc522.PCD_StopCrypto1();
+}
+
+/**
+ * Helper routine to dump a byte array as hex values to Serial.
+ */
+void dump_byte_array(byte *buffer, byte bufferSize) {
+    for (byte i = 0; i < bufferSize; i++) {
+        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+        Serial.print(buffer[i], HEX);
+    }
+}

+ 121 - 0
arduinoLibrary/rc522/MFRC522/examples/ReadNUID/ReadNUID.ino

@@ -0,0 +1,121 @@
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example sketch/program showing how to read new NUID from a PICC to serial.
+ * --------------------------------------------------------------------------------------------------------------------
+ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
+ * 
+ * Example sketch/program showing how to the read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
+ * Reader on the Arduino SPI interface.
+ * 
+ * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
+ * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
+ * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
+ * will show the type, and the NUID if a new card has been detected. Note: you may see "Timeout in communication" messages
+ * when removing the PICC from reading distance too early.
+ * 
+ * @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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define SS_PIN 10
+#define RST_PIN 9
+ 
+MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
+
+// Init array that will store new NUID 
+byte nuidPICC[4];
+
+void setup() { 
+  Serial.begin(9600);
+  SPI.begin(); // Init SPI bus
+  rfid.PCD_Init(); // Init MFRC522 
+
+  Serial.println(F("This code scan the MIFARE Classsic NUID."));
+}
+ 
+void loop() {
+
+  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+  if ( ! rfid.PICC_IsNewCardPresent())
+    return;
+
+  // Verify if the NUID has been readed
+  if ( ! rfid.PICC_ReadCardSerial())
+    return;
+
+  Serial.print(F("PICC type: "));
+  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
+  Serial.println(rfid.PICC_GetTypeName(piccType));
+
+  // Check is the PICC of Classic MIFARE type
+  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
+    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
+    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
+    Serial.println(F("Your tag is not of type MIFARE Classic."));
+    return;
+  }
+
+  if (rfid.uid.uidByte[0] != nuidPICC[0] || 
+    rfid.uid.uidByte[1] != nuidPICC[1] || 
+    rfid.uid.uidByte[2] != nuidPICC[2] || 
+    rfid.uid.uidByte[3] != nuidPICC[3] ) {
+    Serial.println(F("A new card has been detected."));
+
+    // Store NUID into nuidPICC array
+    for (byte i = 0; i < 4; i++) {
+      nuidPICC[i] = rfid.uid.uidByte[i];
+    }
+   
+    Serial.println(F("The NUID tag is:"));
+    Serial.print(F("In hex: "));
+    printHex(rfid.uid.uidByte, rfid.uid.size);
+    Serial.println();
+    Serial.print(F("In dec: "));
+    printDec(rfid.uid.uidByte, rfid.uid.size);
+    Serial.println();
+  }
+  else Serial.println(F("Card read previously."));
+
+  // Halt PICC
+  rfid.PICC_HaltA();
+
+  // Stop encryption on PCD
+  rfid.PCD_StopCrypto1();
+}
+
+
+/**
+ * Helper routine to dump a byte array as hex values to Serial. 
+ */
+void printHex(byte *buffer, byte bufferSize) {
+  for (byte i = 0; i < bufferSize; i++) {
+    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+    Serial.print(buffer[i], HEX);
+  }
+}
+
+/**
+ * Helper routine to dump a byte array as dec values to Serial.
+ */
+void printDec(byte *buffer, byte bufferSize) {
+  for (byte i = 0; i < bufferSize; i++) {
+    Serial.print(' ');
+    Serial.print(buffer[i], DEC);
+  }
+}

+ 99 - 0
arduinoLibrary/rc522/MFRC522/examples/ReadUidMultiReader/ReadUidMultiReader.ino

@@ -0,0 +1,99 @@
+/**
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example sketch/program showing how to read data from more than one PICC to serial.
+ * --------------------------------------------------------------------------------------------------------------------
+ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
+ *
+ * Example sketch/program showing how to read data from more than one PICC (that is: a RFID Tag or Card) using a
+ * MFRC522 based RFID Reader on the Arduino SPI interface.
+ *
+ * Warning: This may not work! Multiple devices at one SPI are difficult and cause many trouble!! Engineering skill
+ *          and knowledge are required!
+ *
+ * @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 1    SDA(SS)      ** custom, take a unused pin, only HIGH/LOW required **
+ * SPI SS 2    SDA(SS)      ** custom, take a unused pin, only HIGH/LOW required **
+ * 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 <SPI.h>
+#include <MFRC522.h>
+
+#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 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
+
+byte ssPins[] = {SS_1_PIN, SS_2_PIN};
+
+MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.
+
+/**
+ * Initialize.
+ */
+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
+
+  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
+    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
+    Serial.print(F("Reader "));
+    Serial.print(reader);
+    Serial.print(F(": "));
+    mfrc522[reader].PCD_DumpVersionToSerial();
+  }
+}
+
+/**
+ * Main loop.
+ */
+void loop() {
+
+  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
+    // Look for new cards
+
+    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
+      Serial.print(F("Reader "));
+      Serial.print(reader);
+      // Show some details of the PICC (that is: the tag/card)
+      Serial.print(F(": Card UID:"));
+      dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
+      Serial.println();
+      Serial.print(F("PICC type: "));
+      MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
+      Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));
+
+      // Halt PICC
+      mfrc522[reader].PICC_HaltA();
+      // Stop encryption on PCD
+      mfrc522[reader].PCD_StopCrypto1();
+    } //if (mfrc522[reader].PICC_IsNewC
+  } //for(uint8_t reader
+}
+
+/**
+ * Helper routine to dump a byte array as hex values to Serial.
+ */
+void dump_byte_array(byte *buffer, byte bufferSize) {
+  for (byte i = 0; i < bufferSize; i++) {
+    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+    Serial.print(buffer[i], HEX);
+  }
+}

+ 63 - 0
arduinoLibrary/rc522/MFRC522/examples/firmware_check/firmware_check.ino

@@ -0,0 +1,63 @@
+/*
+ * --------------------------------------------------------------------------------------------------------------------
+ * Example sketch/program to test your firmware.
+ * --------------------------------------------------------------------------------------------------------------------
+ * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
+ * 
+ * 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.
+ * 
+ * @author Rotzbua
+ * @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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9          // Configurable, see typical pin layout above
+#define SS_PIN          10         // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
+
+/**
+ * Check firmware only once at startup
+ */
+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 module
+  
+  Serial.println(F("*****************************"));
+  Serial.println(F("MFRC522 Digital self test"));
+  Serial.println(F("*****************************"));
+  mfrc522.PCD_DumpVersionToSerial();  // Show version of PCD - MFRC522 Card Reader
+  Serial.println(F("-----------------------------"));
+  Serial.println(F("Only known versions supported"));
+  Serial.println(F("-----------------------------"));
+  Serial.println(F("Performing test..."));
+  bool result = mfrc522.PCD_PerformSelfTest(); // perform the test
+  Serial.println(F("-----------------------------"));
+  Serial.print(F("Result: "));
+  if (result)
+    Serial.println(F("OK"));
+  else
+    Serial.println(F("DEFECT or UNKNOWN"));
+  Serial.println();
+}
+
+void loop() {} // nothing to do

+ 160 - 0
arduinoLibrary/rc522/MFRC522/examples/rfid_default_keys/rfid_default_keys.ino

@@ -0,0 +1,160 @@
+/*
+ * ----------------------------------------------------------------------------
+ * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
+ * for further details and other examples.
+ * 
+ * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
+ * 
+ * Released into the public domain.
+ * ----------------------------------------------------------------------------
+ * Example sketch/program which will try the most used default keys listed in 
+ * https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys to dump the
+ * block 0 of a MIFARE RFID card using a RFID-RC522 reader.
+ * 
+ * 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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+ *
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+
+// Number of known default keys (hard-coded)
+// NOTE: Synchronize the NR_KNOWN_KEYS define with the defaultKeys[] array
+#define NR_KNOWN_KEYS   8
+// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
+byte knownKeys[NR_KNOWN_KEYS][MFRC522::MF_KEY_SIZE] =  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // FF FF FF FF FF FF = factory default
+    {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}, // A0 A1 A2 A3 A4 A5
+    {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5}, // B0 B1 B2 B3 B4 B5
+    {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd}, // 4D 3A 99 C3 51 DD
+    {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a}, // 1A 98 2C 7E 45 9A
+    {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}, // D3 F7 D3 F7 D3 F7
+    {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, // AA BB CC DD EE FF
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  // 00 00 00 00 00 00
+};
+
+/*
+ * Initialize.
+ */
+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("Try the most used default keys to print block 0 of a MIFARE PICC."));
+}
+
+/*
+ * Helper routine to dump a byte array as hex values to Serial.
+ */
+void dump_byte_array(byte *buffer, byte bufferSize) {
+    for (byte i = 0; i < bufferSize; i++) {
+        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
+        Serial.print(buffer[i], HEX);
+    }
+}
+
+/*
+ * Try using the PICC (the tag/card) with the given key to access block 0.
+ * On success, it will show the key details, and dump the block data on Serial.
+ *
+ * @return true when the given key worked, false otherwise.
+ */
+bool try_key(MFRC522::MIFARE_Key *key)
+{
+    bool result = false;
+    byte buffer[18];
+    byte block = 0;
+    MFRC522::StatusCode status;
+
+    // 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) {
+        // Serial.print(F("PCD_Authenticate() failed: "));
+        // Serial.println(mfrc522.GetStatusCodeName(status));
+        return false;
+    }
+
+    // Read block
+    byte byteCount = sizeof(buffer);
+    status = mfrc522.MIFARE_Read(block, buffer, &byteCount);
+    if (status != MFRC522::STATUS_OK) {
+        // Serial.print(F("MIFARE_Read() failed: "));
+        // Serial.println(mfrc522.GetStatusCodeName(status));
+    }
+    else {
+        // Successful read
+        result = true;
+        Serial.print(F("Success with key:"));
+        dump_byte_array((*key).keyByte, MFRC522::MF_KEY_SIZE);
+        Serial.println();
+        // Dump block data
+        Serial.print(F("Block ")); Serial.print(block); Serial.print(F(":"));
+        dump_byte_array(buffer, 16);
+        Serial.println();
+    }
+    Serial.println();
+
+    mfrc522.PICC_HaltA();       // Halt PICC
+    mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
+    return result;
+}
+
+/*
+ * Main loop.
+ */
+void loop() {
+    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+    if ( ! mfrc522.PICC_IsNewCardPresent())
+        return;
+
+    // Select one of the cards
+    if ( ! mfrc522.PICC_ReadCardSerial())
+        return;
+
+    // Show some details of the PICC (that is: the tag/card)
+    Serial.print(F("Card UID:"));
+    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
+    Serial.println();
+    Serial.print(F("PICC type: "));
+    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+    Serial.println(mfrc522.PICC_GetTypeName(piccType));
+    
+    // Try the known default keys
+    MFRC522::MIFARE_Key key;
+    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
+        // Copy the known key into the MIFARE_Key structure
+        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
+            key.keyByte[i] = knownKeys[k][i];
+        }
+        // Try the key
+        if (try_key(&key)) {
+            // Found and reported on the key and block,
+            // 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;
+    }
+}

+ 140 - 0
arduinoLibrary/rc522/MFRC522/examples/rfid_read_personal_data/rfid_read_personal_data.ino

@@ -0,0 +1,140 @@
+/*
+ * Initial Author: ryand1011 (https://github.com/ryand1011)
+ *
+ * Reads data written by a program such as "rfid_write_personal_data.ino"
+ *
+ * See: https://github.com/miguelbalboa/rfid/tree/master/examples/rfid_write_personal_data
+ *
+ * Uses MIFARE RFID card using RFID-RC522 reader
+ * Uses MFRC522 - Library
+ * -----------------------------------------------------------------------------------------
+ *             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
+ *
+ * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
+*/
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
+
+//*****************************************************************************************//
+void setup() {
+  Serial.begin(9600);                                           // Initialize serial communications with the PC
+  SPI.begin();                                                  // Init SPI bus
+  mfrc522.PCD_Init();                                              // Init MFRC522 card
+  Serial.println(F("Read personal data on a MIFARE PICC:"));    //shows in serial that it is ready to read
+}
+
+//*****************************************************************************************//
+void loop() {
+
+  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
+  MFRC522::MIFARE_Key key;
+  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
+
+  //some variables we need
+  byte block;
+  byte len;
+  MFRC522::StatusCode status;
+
+  //-------------------------------------------
+
+  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+  if ( ! mfrc522.PICC_IsNewCardPresent()) {
+    return;
+  }
+
+  // Select one of the cards
+  if ( ! mfrc522.PICC_ReadCardSerial()) {
+    return;
+  }
+
+  Serial.println(F("**Card Detected:**"));
+
+  //-------------------------------------------
+
+  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card
+
+  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex
+
+  //-------------------------------------------
+
+  Serial.print(F("Name: "));
+
+  byte buffer1[18];
+
+  block = 4;
+  len = 18;
+
+  //------------------------------------------- GET FIRST NAME
+  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("Authentication failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  status = mfrc522.MIFARE_Read(block, buffer1, &len);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("Reading failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  //PRINT FIRST NAME
+  for (uint8_t i = 0; i < 16; i++)
+  {
+    if (buffer1[i] != 32)
+    {
+      Serial.write(buffer1[i]);
+    }
+  }
+  Serial.print(" ");
+
+  //---------------------------------------- GET LAST NAME
+
+  byte buffer2[18];
+  block = 1;
+
+  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("Authentication failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  status = mfrc522.MIFARE_Read(block, buffer2, &len);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("Reading failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  //PRINT LAST NAME
+  for (uint8_t i = 0; i < 16; i++) {
+    Serial.write(buffer2[i] );
+  }
+
+
+  //----------------------------------------
+
+  Serial.println(F("\n**End Reading**\n"));
+
+  delay(1000); //change value if you want to read cards faster
+
+  mfrc522.PICC_HaltA();
+  mfrc522.PCD_StopCrypto1();
+}
+//*****************************************************************************************//

+ 158 - 0
arduinoLibrary/rc522/MFRC522/examples/rfid_write_personal_data/rfid_write_personal_data.ino

@@ -0,0 +1,158 @@
+/*
+ * Write personal data of a MIFARE RFID card using a RFID-RC522 reader
+ * Uses MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT. 
+ * -----------------------------------------------------------------------------------------
+ *             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
+ *
+ * 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
+ * PICC (Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
+ * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com. 
+ */
+
+#include <SPI.h>
+#include <MFRC522.h>
+
+#define RST_PIN         9           // Configurable, see typical pin layout above
+#define SS_PIN          10          // Configurable, see typical pin layout above
+
+MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
+
+void setup() {
+  Serial.begin(9600);        // Initialize serial communications with the PC
+  SPI.begin();               // Init SPI bus
+  mfrc522.PCD_Init();        // Init MFRC522 card
+  Serial.println(F("Write personal data on a MIFARE PICC "));
+}
+
+void loop() {
+
+  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
+  MFRC522::MIFARE_Key key;
+  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
+
+  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
+  if ( ! mfrc522.PICC_IsNewCardPresent()) {
+    return;
+  }
+
+  // Select one of the cards
+  if ( ! mfrc522.PICC_ReadCardSerial()) {
+    return;
+  }
+
+  Serial.print(F("Card UID:"));    //Dump UID
+  for (byte i = 0; i < mfrc522.uid.size; i++) {
+    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
+    Serial.print(mfrc522.uid.uidByte[i], HEX);
+  }
+  Serial.print(F(" PICC type: "));   // Dump PICC type
+  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
+  Serial.println(mfrc522.PICC_GetTypeName(piccType));
+
+  byte buffer[34];
+  byte block;
+  MFRC522::StatusCode status;
+  byte len;
+
+  Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
+  // Ask personal data: Family name
+  Serial.println(F("Type Family name, ending with #"));
+  len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
+  for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces
+
+  block = 1;
+  //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) {
+    Serial.print(F("PCD_Authenticate() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+  else Serial.println(F("PCD_Authenticate() success: "));
+
+  // Write block
+  status = mfrc522.MIFARE_Write(block, buffer, 16);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("MIFARE_Write() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+  else Serial.println(F("MIFARE_Write() success: "));
+
+  block = 2;
+  //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) {
+    Serial.print(F("PCD_Authenticate() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  // Write block
+  status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("MIFARE_Write() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+  else Serial.println(F("MIFARE_Write() success: "));
+
+  // Ask personal data: First name
+  Serial.println(F("Type First name, ending with #"));
+  len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
+  for (byte i = len; i < 20; i++) buffer[i] = ' ';     // pad with spaces
+
+  block = 4;
+  //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) {
+    Serial.print(F("PCD_Authenticate() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  // Write block
+  status = mfrc522.MIFARE_Write(block, buffer, 16);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("MIFARE_Write() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+  else Serial.println(F("MIFARE_Write() success: "));
+
+  block = 5;
+  //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) {
+    Serial.print(F("PCD_Authenticate() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+
+  // Write block
+  status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
+  if (status != MFRC522::STATUS_OK) {
+    Serial.print(F("MIFARE_Write() failed: "));
+    Serial.println(mfrc522.GetStatusCodeName(status));
+    return;
+  }
+  else Serial.println(F("MIFARE_Write() success: "));
+
+
+  Serial.println(" ");
+  mfrc522.PICC_HaltA(); // Halt PICC
+  mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
+
+}

+ 223 - 0
arduinoLibrary/rc522/MFRC522/keywords.txt

@@ -0,0 +1,223 @@
+#######################################
+# Syntax Coloring Map for library MFRC522
+#######################################
+
+#######################################
+# KEYWORD1 Classes, datatypes, and C++ keywords
+#######################################
+MFRC522	KEYWORD1
+MFRC522Extended	KEYWORD1
+PCD_Register	KEYWORD1
+PCD_Command	KEYWORD1
+PCD_RxGain	KEYWORD1
+PICC_Command	KEYWORD1
+MIFARE_Misc	KEYWORD1
+PICC_Type	KEYWORD1
+StatusCode	KEYWORD1
+TagBitRates	KEYWORD1
+Uid	KEYWORD1
+CardInfo	KEYWORD1
+MIFARE_Key	KEYWORD1
+PcbBlock	KEYWORD1
+ 
+#######################################
+# KEYWORD2 Methods and functions
+#######################################
+
+# Basic interface functions for communicating with the MFRC522
+PCD_WriteRegister	KEYWORD2
+PCD_WriteRegister	KEYWORD2
+PCD_ReadRegister	KEYWORD2
+PCD_ReadRegister	KEYWORD2
+setBitMask	KEYWORD2
+PCD_SetRegisterBitMask	KEYWORD2
+PCD_ClearRegisterBitMask	KEYWORD2
+PCD_CalculateCRC	KEYWORD2
+
+# Functions for manipulating the MFRC522
+PCD_Init	KEYWORD2
+PCD_Reset	KEYWORD2
+PCD_AntennaOn	KEYWORD2
+PCD_AntennaOff	KEYWORD2
+PCD_GetAntennaGain	KEYWORD2
+PCD_SetAntennaGain	KEYWORD2
+PCD_PerformSelfTest	KEYWORD2
+
+# Power control functions MFRC522
+PCD_SoftPowerDown	KEYWORD2
+PCD_SoftPowerUp	KEYWORD2
+
+# Functions for communicating with PICCs
+PCD_TransceiveData	KEYWORD2
+PCD_CommunicateWithPICC	KEYWORD2
+PICC_RequestA	KEYWORD2
+PICC_WakeupA	KEYWORD2
+PICC_REQA_or_WUPA	KEYWORD2
+PICC_Select	KEYWORD2
+PICC_HaltA	KEYWORD2
+PICC_RATS	KEYWORD2
+PICC_PPS	KEYWORD2
+
+# Functions for communicating with ISO/IEC 14433-4 cards
+TCL_Transceive	KEYWORD2
+TCL_TransceiveRBlock	KEYWORD2
+TCL_Deselect	KEYWORD2
+
+# Functions for communicating with MIFARE PICCs
+PCD_Authenticate	KEYWORD2
+PCD_StopCrypto1	KEYWORD2
+MIFARE_Read	KEYWORD2
+MIFARE_Write	KEYWORD2
+MIFARE_Increment	KEYWORD2
+MIFARE_Ultralight_Write	KEYWORD2
+MIFARE_GetValue	KEYWORD2
+MIFARE_SetValue	KEYWORD2
+PCD_NTAG216_AUTH	KEYWORD2
+
+# Support functions
+PCD_MIFARE_Transceive	KEYWORD2
+GetStatusCodeName	KEYWORD2
+PICC_GetType	KEYWORD2
+PICC_GetTypeName	KEYWORD2
+
+# Support functions for debuging
+PCD_DumpVersionToSerial	KEYWORD2
+PICC_DumpToSerial	KEYWORD2
+PICC_DumpDetailsToSerial	KEYWORD2
+PICC_DumpMifareClassicToSerial	KEYWORD2
+PICC_DumpMifareClassicSectorToSerial	KEYWORD2
+PICC_DumpMifareUltralightToSerial	KEYWORD2
+PICC_DumpISO14443_4	KEYWORD2
+
+# Advanced functions for MIFARE
+MIFARE_SetAccessBits	KEYWORD2
+MIFARE_OpenUidBackdoor	KEYWORD2
+MIFARE_SetUid	KEYWORD2
+MIFARE_UnbrickUidSector	KEYWORD2
+
+# Convenience functions - does not add extra functionality
+PICC_IsNewCardPresent	KEYWORD2
+PICC_ReadCardSerial	KEYWORD2
+
+#######################################
+# KEYWORD3 setup and loop functions, as well as the Serial keywords
+#######################################
+
+#######################################
+# LITERAL1 Constants
+#######################################
+CommandReg	LITERAL1
+ComIEnReg	LITERAL1
+DivIEnReg	LITERAL1
+ComIrqReg	LITERAL1
+DivIrqReg	LITERAL1
+ErrorReg	LITERAL1
+Status1Reg	LITERAL1
+Status2Reg	LITERAL1
+FIFODataReg	LITERAL1
+FIFOLevelReg	LITERAL1
+WaterLevelReg	LITERAL1
+ControlReg	LITERAL1
+BitFramingReg	LITERAL1
+CollReg	LITERAL1
+ModeReg	LITERAL1
+TxModeReg	LITERAL1
+RxModeReg	LITERAL1
+TxControlReg	LITERAL1
+TxASKReg	LITERAL1
+TxSelReg	LITERAL1
+RxSelReg	LITERAL1
+RxThresholdReg	LITERAL1
+DemodReg	LITERAL1
+MfTxReg	LITERAL1
+MfRxReg	LITERAL1
+SerialSpeedReg	LITERAL1
+CRCResultRegH	LITERAL1
+CRCResultRegL	LITERAL1
+ModWidthReg	LITERAL1
+RFCfgReg	LITERAL1
+GsNReg	LITERAL1
+CWGsPReg	LITERAL1
+ModGsPReg	LITERAL1
+TModeReg	LITERAL1
+TPrescalerReg	LITERAL1
+TReloadRegH	LITERAL1
+TReloadRegL	LITERAL1
+TCounterValueRegH	LITERAL1
+TCounterValueRegL	LITERAL1
+TestSel1Reg	LITERAL1
+TestSel2Reg	LITERAL1
+TestPinEnReg	LITERAL1
+TestPinValueReg	LITERAL1
+TestBusReg	LITERAL1
+AutoTestReg	LITERAL1
+VersionReg	LITERAL1
+AnalogTestReg	LITERAL1
+TestDAC1Reg	LITERAL1
+TestDAC2Reg	LITERAL1
+TestADCReg	LITERAL1
+PCD_Idle	LITERAL1
+PCD_Mem	LITERAL1
+PCD_GenerateRandomID	LITERAL1
+PCD_CalcCRC	LITERAL1
+PCD_Transmit	LITERAL1
+PCD_NoCmdChange	LITERAL1
+PCD_Receive	LITERAL1
+PCD_Transceive	LITERAL1
+PCD_MFAuthent	LITERAL1
+PCD_SoftReset	LITERAL1
+RxGain_18dB	LITERAL1
+RxGain_23dB	LITERAL1
+RxGain_18dB_2	LITERAL1
+RxGain_23dB_2	LITERAL1
+RxGain_33dB	LITERAL1
+RxGain_38dB	LITERAL1
+RxGain_43dB	LITERAL1
+RxGain_48dB	LITERAL1
+RxGain_min	LITERAL1
+RxGain_avg	LITERAL1
+RxGain_max	LITERAL1
+PICC_CMD_REQA	LITERAL1
+PICC_CMD_WUPA	LITERAL1
+PICC_CMD_CT	LITERAL1
+PICC_CMD_SEL_CL1	LITERAL1
+PICC_CMD_SEL_CL2	LITERAL1
+PICC_CMD_SEL_CL3	LITERAL1
+PICC_CMD_HLTA	LITERAL1
+PICC_CMD_RATS	LITERAL1
+PICC_CMD_MF_AUTH_KEY_A	LITERAL1
+PICC_CMD_MF_AUTH_KEY_B	LITERAL1
+PICC_CMD_MF_READ	LITERAL1
+PICC_CMD_MF_WRITE	LITERAL1
+PICC_CMD_MF_DECREMENT	LITERAL1
+PICC_CMD_MF_INCREMENT	LITERAL1
+PICC_CMD_MF_RESTORE	LITERAL1
+PICC_CMD_MF_TRANSFER	LITERAL1
+PICC_CMD_UL_WRITE	LITERAL1
+MF_ACK	LITERAL1
+MF_KEY_SIZE	LITERAL1
+PICC_TYPE_UNKNOWN	LITERAL1
+PICC_TYPE_ISO_14443_4	LITERAL1
+PICC_TYPE_ISO_18092	LITERAL1
+PICC_TYPE_MIFARE_MINI	LITERAL1
+PICC_TYPE_MIFARE_1K	LITERAL1
+PICC_TYPE_MIFARE_4K	LITERAL1
+PICC_TYPE_MIFARE_UL	LITERAL1
+PICC_TYPE_MIFARE_PLUS	LITERAL1
+PICC_TYPE_MIFARE_DESFIRE	LITERAL1
+PICC_TYPE_TNP3XXX	LITERAL1
+PICC_TYPE_NOT_COMPLETE	LITERAL1
+STATUS_OK	LITERAL1
+STATUS_ERROR	LITERAL1
+STATUS_COLLISION	LITERAL1
+STATUS_TIMEOUT	LITERAL1
+STATUS_NO_ROOM	LITERAL1
+STATUS_INTERNAL_ERROR	LITERAL1
+STATUS_INVALID	LITERAL1
+STATUS_CRC_WRONG	LITERAL1
+STATUS_MIFARE_NACK	LITERAL1
+FIFO_SIZE	LITERAL1
+BITRATE_106KBITS	LITERAL1
+BITRATE_212KBITS	LITERAL1
+BITRATE_424KBITS	LITERAL1
+BITRATE_848KBITS	LITERAL1

+ 15 - 0
arduinoLibrary/rc522/MFRC522/library.json

@@ -0,0 +1,15 @@
+{
+  "name": "MFRC522",
+  "version": "1.4.12",
+  "license": "Unlicense",
+  "keywords": "rfid, spi",
+  "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"
+  },
+  "exclude": "doc",
+  "frameworks": "arduino",
+  "platforms": ["atmelavr", "atmelsam", "ststm32", "espressif8266", "espressif32", "samd", "rp2040"]
+}

+ 9 - 0
arduinoLibrary/rc522/MFRC522/library.properties

@@ -0,0 +1,9 @@
+name=MFRC522
+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,megaavr,STM32F1,teensy,esp8266,esp32,samd,atmelsam,rp2040

File diff suppressed because it is too large
+ 1950 - 0
arduinoLibrary/rc522/MFRC522/src/MFRC522.cpp


+ 371 - 0
arduinoLibrary/rc522/MFRC522/src/MFRC522.h

@@ -0,0 +1,371 @@
+/**
+ * Library to use Arduino MFRC522 module.
+ * 
+ * @authors Dr.Leong, Miguel Balboa, Søren Thing Andersen, Tom Clement, many more! See GitLog.
+ * 
+ * For more information read the README.
+ * 
+ * Please read this file for an overview and then MFRC522.cpp for comments on the specific functions.
+ */
+#ifndef MFRC522_h
+#define MFRC522_h
+
+#include "require_cpp11.h"
+#include "deprecated.h"
+// Enable integer limits
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include <Arduino.h>
+#include <SPI.h>
+
+#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
+// Hint: if needed, you can remove unused self-test data to save flash memory
+//
+// Version 0.0 (0x90)
+// Philips Semiconductors; Preliminary Specification Revision 2.0 - 01 August 2005; 16.1 self-test
+const byte MFRC522_firmware_referenceV0_0[] PROGMEM = {
+	0x00, 0x87, 0x98, 0x0f, 0x49, 0xFF, 0x07, 0x19,
+	0xBF, 0x22, 0x30, 0x49, 0x59, 0x63, 0xAD, 0xCA,
+	0x7F, 0xE3, 0x4E, 0x03, 0x5C, 0x4E, 0x49, 0x50,
+	0x47, 0x9A, 0x37, 0x61, 0xE7, 0xE2, 0xC6, 0x2E,
+	0x75, 0x5A, 0xED, 0x04, 0x3D, 0x02, 0x4B, 0x78,
+	0x32, 0xFF, 0x58, 0x3B, 0x7C, 0xE9, 0x00, 0x94,
+	0xB4, 0x4A, 0x59, 0x5B, 0xFD, 0xC9, 0x29, 0xDF,
+	0x35, 0x96, 0x98, 0x9E, 0x4F, 0x30, 0x32, 0x8D
+};
+// Version 1.0 (0x91)
+// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 self-test
+const byte MFRC522_firmware_referenceV1_0[] PROGMEM = {
+	0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C,
+	0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73,
+	0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A,
+	0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E,
+	0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC,
+	0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41,
+	0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02,
+	0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79
+};
+// Version 2.0 (0x92)
+// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 self-test
+const byte MFRC522_firmware_referenceV2_0[] PROGMEM = {
+	0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95,
+	0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE,
+	0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82,
+	0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49,
+	0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81,
+	0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9,
+	0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D,
+	0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
+};
+// Clone
+// Fudan Semiconductor FM17522 (0x88)
+const byte FM17522_firmware_reference[] PROGMEM = {
+	0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18,
+	0x2A, 0xB8, 0x7A, 0x7F, 0xD3, 0x6A, 0xCF, 0x0B,
+	0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE, 0x91, 0xC7,
+	0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B,
+	0x7C, 0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7,
+	0xC1, 0x5B, 0x00, 0x2A, 0xD0, 0x75, 0xDE, 0x9E,
+	0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5, 0xAB,
+	0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62
+};
+
+class MFRC522 {
+public:
+	// Size of the MFRC522 FIFO
+	static constexpr byte FIFO_SIZE = 64;		// The FIFO is 64 bytes.
+	// Default value for unused pin
+	static constexpr uint8_t UNUSED_PIN = UINT8_MAX;
+
+	// MFRC522 registers. Described in chapter 9 of the datasheet.
+	// When using SPI all addresses are shifted one bit left in the "SPI address byte" (section 8.1.2.3)
+	enum PCD_Register : byte {
+		// Page 0: Command and status
+		//						  0x00			// reserved for future use
+		CommandReg				= 0x01 << 1,	// starts and stops command execution
+		ComIEnReg				= 0x02 << 1,	// enable and disable interrupt request control bits
+		DivIEnReg				= 0x03 << 1,	// enable and disable interrupt request control bits
+		ComIrqReg				= 0x04 << 1,	// interrupt request bits
+		DivIrqReg				= 0x05 << 1,	// interrupt request bits
+		ErrorReg				= 0x06 << 1,	// error bits showing the error status of the last command executed 
+		Status1Reg				= 0x07 << 1,	// communication status bits
+		Status2Reg				= 0x08 << 1,	// receiver and transmitter status bits
+		FIFODataReg				= 0x09 << 1,	// input and output of 64 byte FIFO buffer
+		FIFOLevelReg			= 0x0A << 1,	// number of bytes stored in the FIFO buffer
+		WaterLevelReg			= 0x0B << 1,	// level for FIFO underflow and overflow warning
+		ControlReg				= 0x0C << 1,	// miscellaneous control registers
+		BitFramingReg			= 0x0D << 1,	// adjustments for bit-oriented frames
+		CollReg					= 0x0E << 1,	// bit position of the first bit-collision detected on the RF interface
+		//						  0x0F			// reserved for future use
+		
+		// Page 1: Command
+		// 						  0x10			// reserved for future use
+		ModeReg					= 0x11 << 1,	// defines general modes for transmitting and receiving 
+		TxModeReg				= 0x12 << 1,	// defines transmission data rate and framing
+		RxModeReg				= 0x13 << 1,	// defines reception data rate and framing
+		TxControlReg			= 0x14 << 1,	// controls the logical behavior of the antenna driver pins TX1 and TX2
+		TxASKReg				= 0x15 << 1,	// controls the setting of the transmission modulation
+		TxSelReg				= 0x16 << 1,	// selects the internal sources for the antenna driver
+		RxSelReg				= 0x17 << 1,	// selects internal receiver settings
+		RxThresholdReg			= 0x18 << 1,	// selects thresholds for the bit decoder
+		DemodReg				= 0x19 << 1,	// defines demodulator settings
+		// 						  0x1A			// reserved for future use
+		// 						  0x1B			// reserved for future use
+		MfTxReg					= 0x1C << 1,	// controls some MIFARE communication transmit parameters
+		MfRxReg					= 0x1D << 1,	// controls some MIFARE communication receive parameters
+		// 						  0x1E			// reserved for future use
+		SerialSpeedReg			= 0x1F << 1,	// selects the speed of the serial UART interface
+		
+		// Page 2: Configuration
+		// 						  0x20			// reserved for future use
+		CRCResultRegH			= 0x21 << 1,	// shows the MSB and LSB values of the CRC calculation
+		CRCResultRegL			= 0x22 << 1,
+		// 						  0x23			// reserved for future use
+		ModWidthReg				= 0x24 << 1,	// controls the ModWidth setting?
+		// 						  0x25			// reserved for future use
+		RFCfgReg				= 0x26 << 1,	// configures the receiver gain
+		GsNReg					= 0x27 << 1,	// selects the conductance of the antenna driver pins TX1 and TX2 for modulation 
+		CWGsPReg				= 0x28 << 1,	// defines the conductance of the p-driver output during periods of no modulation
+		ModGsPReg				= 0x29 << 1,	// defines the conductance of the p-driver output during periods of modulation
+		TModeReg				= 0x2A << 1,	// defines settings for the internal timer
+		TPrescalerReg			= 0x2B << 1,	// the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
+		TReloadRegH				= 0x2C << 1,	// defines the 16-bit timer reload value
+		TReloadRegL				= 0x2D << 1,
+		TCounterValueRegH		= 0x2E << 1,	// shows the 16-bit timer value
+		TCounterValueRegL		= 0x2F << 1,
+		
+		// Page 3: Test Registers
+		// 						  0x30			// reserved for future use
+		TestSel1Reg				= 0x31 << 1,	// general test signal configuration
+		TestSel2Reg				= 0x32 << 1,	// general test signal configuration
+		TestPinEnReg			= 0x33 << 1,	// enables pin output driver on pins D1 to D7
+		TestPinValueReg			= 0x34 << 1,	// defines the values for D1 to D7 when it is used as an I/O bus
+		TestBusReg				= 0x35 << 1,	// shows the status of the internal test bus
+		AutoTestReg				= 0x36 << 1,	// controls the digital self-test
+		VersionReg				= 0x37 << 1,	// shows the software version
+		AnalogTestReg			= 0x38 << 1,	// controls the pins AUX1 and AUX2
+		TestDAC1Reg				= 0x39 << 1,	// defines the test value for TestDAC1
+		TestDAC2Reg				= 0x3A << 1,	// defines the test value for TestDAC2
+		TestADCReg				= 0x3B << 1		// shows the value of ADC I and Q channels
+		// 						  0x3C			// reserved for production tests
+		// 						  0x3D			// reserved for production tests
+		// 						  0x3E			// reserved for production tests
+		// 						  0x3F			// reserved for production tests
+	};
+	
+	// MFRC522 commands. Described in chapter 10 of the datasheet.
+	enum PCD_Command : byte {
+		PCD_Idle				= 0x00,		// no action, cancels current command execution
+		PCD_Mem					= 0x01,		// stores 25 bytes into the internal buffer
+		PCD_GenerateRandomID	= 0x02,		// generates a 10-byte random ID number
+		PCD_CalcCRC				= 0x03,		// activates the CRC coprocessor or performs a self-test
+		PCD_Transmit			= 0x04,		// transmits data from the FIFO buffer
+		PCD_NoCmdChange			= 0x07,		// no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
+		PCD_Receive				= 0x08,		// activates the receiver circuits
+		PCD_Transceive 			= 0x0C,		// transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
+		PCD_MFAuthent 			= 0x0E,		// performs the MIFARE standard authentication as a reader
+		PCD_SoftReset			= 0x0F		// resets the MFRC522
+	};
+	
+	// MFRC522 RxGain[2:0] masks, defines the receiver's signal voltage gain factor (on the PCD).
+	// Described in 9.3.3.6 / table 98 of the datasheet at http://www.nxp.com/documents/data_sheet/MFRC522.pdf
+	enum PCD_RxGain : byte {
+		RxGain_18dB				= 0x00 << 4,	// 000b - 18 dB, minimum
+		RxGain_23dB				= 0x01 << 4,	// 001b - 23 dB
+		RxGain_18dB_2			= 0x02 << 4,	// 010b - 18 dB, it seems 010b is a duplicate for 000b
+		RxGain_23dB_2			= 0x03 << 4,	// 011b - 23 dB, it seems 011b is a duplicate for 001b
+		RxGain_33dB				= 0x04 << 4,	// 100b - 33 dB, average, and typical default
+		RxGain_38dB				= 0x05 << 4,	// 101b - 38 dB
+		RxGain_43dB				= 0x06 << 4,	// 110b - 43 dB
+		RxGain_48dB				= 0x07 << 4,	// 111b - 48 dB, maximum
+		RxGain_min				= 0x00 << 4,	// 000b - 18 dB, minimum, convenience for RxGain_18dB
+		RxGain_avg				= 0x04 << 4,	// 100b - 33 dB, average, convenience for RxGain_33dB
+		RxGain_max				= 0x07 << 4		// 111b - 48 dB, maximum, convenience for RxGain_48dB
+	};
+	
+	// Commands sent to the PICC.
+	enum PICC_Command : byte {
+		// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
+		PICC_CMD_REQA			= 0x26,		// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
+		PICC_CMD_WUPA			= 0x52,		// Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
+		PICC_CMD_CT				= 0x88,		// Cascade Tag. Not really a command, but used during anti collision.
+		PICC_CMD_SEL_CL1		= 0x93,		// Anti collision/Select, Cascade Level 1
+		PICC_CMD_SEL_CL2		= 0x95,		// Anti collision/Select, Cascade Level 2
+		PICC_CMD_SEL_CL3		= 0x97,		// Anti collision/Select, Cascade Level 3
+		PICC_CMD_HLTA			= 0x50,		// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
+		PICC_CMD_RATS           = 0xE0,     // Request command for Answer To Reset.
+		// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
+		// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
+		// The read/write commands can also be used for MIFARE Ultralight.
+		PICC_CMD_MF_AUTH_KEY_A	= 0x60,		// Perform authentication with Key A
+		PICC_CMD_MF_AUTH_KEY_B	= 0x61,		// Perform authentication with Key B
+		PICC_CMD_MF_READ		= 0x30,		// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
+		PICC_CMD_MF_WRITE		= 0xA0,		// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
+		PICC_CMD_MF_DECREMENT	= 0xC0,		// Decrements the contents of a block and stores the result in the internal data register.
+		PICC_CMD_MF_INCREMENT	= 0xC1,		// Increments the contents of a block and stores the result in the internal data register.
+		PICC_CMD_MF_RESTORE		= 0xC2,		// Reads the contents of a block into the internal data register.
+		PICC_CMD_MF_TRANSFER	= 0xB0,		// Writes the contents of the internal data register to a block.
+		// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
+		// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
+		PICC_CMD_UL_WRITE		= 0xA2		// Writes one 4 byte page to the PICC.
+	};
+	
+	// MIFARE constants that does not fit anywhere else
+	enum MIFARE_Misc {
+		MF_ACK					= 0xA,		// The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
+		MF_KEY_SIZE				= 6			// A Mifare Crypto1 key is 6 bytes.
+	};
+	
+	// PICC types we can detect. Remember to update PICC_GetTypeName() if you add more.
+	// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
+	enum PICC_Type : byte {
+		PICC_TYPE_UNKNOWN		,
+		PICC_TYPE_ISO_14443_4	,	// PICC compliant with ISO/IEC 14443-4 
+		PICC_TYPE_ISO_18092		, 	// PICC compliant with ISO/IEC 18092 (NFC)
+		PICC_TYPE_MIFARE_MINI	,	// MIFARE Classic protocol, 320 bytes
+		PICC_TYPE_MIFARE_1K		,	// MIFARE Classic protocol, 1KB
+		PICC_TYPE_MIFARE_4K		,	// MIFARE Classic protocol, 4KB
+		PICC_TYPE_MIFARE_UL		,	// MIFARE Ultralight or Ultralight C
+		PICC_TYPE_MIFARE_PLUS	,	// MIFARE Plus
+		PICC_TYPE_MIFARE_DESFIRE,	// MIFARE DESFire
+		PICC_TYPE_TNP3XXX		,	// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
+		PICC_TYPE_NOT_COMPLETE	= 0xff	// SAK indicates UID is not complete.
+	};
+	
+	// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
+	// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
+	enum StatusCode : byte {
+		STATUS_OK				,	// Success
+		STATUS_ERROR			,	// Error in communication
+		STATUS_COLLISION		,	// Collission detected
+		STATUS_TIMEOUT			,	// Timeout in communication.
+		STATUS_NO_ROOM			,	// A buffer is not big enough.
+		STATUS_INTERNAL_ERROR	,	// Internal error in the code. Should not happen ;-)
+		STATUS_INVALID			,	// Invalid argument.
+		STATUS_CRC_WRONG		,	// The CRC_A does not match
+		STATUS_MIFARE_NACK		= 0xff	// A MIFARE PICC responded with NAK.
+	};
+	
+	// A struct used for passing the UID of a PICC.
+	typedef struct {
+		byte		size;			// Number of bytes in the UID. 4, 7 or 10.
+		byte		uidByte[10];
+		byte		sak;			// The SAK (Select acknowledge) byte returned from the PICC after successful selection.
+	} Uid;
+
+	// A struct used for passing a MIFARE Crypto1 key
+	typedef struct {
+		byte		keyByte[MF_KEY_SIZE];
+	} MIFARE_Key;
+	
+	// Member variables
+	Uid uid;								// Used by PICC_ReadCardSerial().
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for setting up the Arduino
+	/////////////////////////////////////////////////////////////////////////////////////
+	MFRC522();
+	MFRC522(byte resetPowerDownPin);
+	MFRC522(byte chipSelectPin, byte resetPowerDownPin);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Basic interface functions for communicating with the MFRC522
+	/////////////////////////////////////////////////////////////////////////////////////
+	void PCD_WriteRegister(PCD_Register reg, byte value);
+	void PCD_WriteRegister(PCD_Register reg, byte count, byte *values);
+	byte PCD_ReadRegister(PCD_Register reg);
+	void PCD_ReadRegister(PCD_Register reg, byte count, byte *values, byte rxAlign = 0);
+	void PCD_SetRegisterBitMask(PCD_Register reg, byte mask);
+	void PCD_ClearRegisterBitMask(PCD_Register reg, byte mask);
+	StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for manipulating the MFRC522
+	/////////////////////////////////////////////////////////////////////////////////////
+	void PCD_Init();
+	void PCD_Init(byte resetPowerDownPin);
+	void PCD_Init(byte chipSelectPin, byte resetPowerDownPin);
+	void PCD_Reset();
+	void PCD_AntennaOn();
+	void PCD_AntennaOff();
+	byte PCD_GetAntennaGain();
+	void PCD_SetAntennaGain(byte mask);
+	bool PCD_PerformSelfTest();
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Power control functions
+	/////////////////////////////////////////////////////////////////////////////////////
+	void PCD_SoftPowerDown();
+	void PCD_SoftPowerUp();
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for communicating with PICCs
+	/////////////////////////////////////////////////////////////////////////////////////
+	StatusCode PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = nullptr, byte rxAlign = 0, bool checkCRC = false);
+	StatusCode PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = nullptr, byte *backLen = nullptr, byte *validBits = nullptr, byte rxAlign = 0, bool checkCRC = false);
+	StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
+	StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
+	StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
+	virtual StatusCode PICC_Select(Uid *uid, byte validBits = 0);
+	StatusCode PICC_HaltA();
+
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for communicating with MIFARE PICCs
+	/////////////////////////////////////////////////////////////////////////////////////
+	StatusCode PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
+	void PCD_StopCrypto1();
+	StatusCode MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
+	StatusCode MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
+	StatusCode MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
+	StatusCode MIFARE_Decrement(byte blockAddr, int32_t delta);
+	StatusCode MIFARE_Increment(byte blockAddr, int32_t delta);
+	StatusCode MIFARE_Restore(byte blockAddr);
+	StatusCode MIFARE_Transfer(byte blockAddr);
+	StatusCode MIFARE_GetValue(byte blockAddr, int32_t *value);
+	StatusCode MIFARE_SetValue(byte blockAddr, int32_t value);
+	StatusCode PCD_NTAG216_AUTH(byte *passWord, byte pACK[]);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Support functions
+	/////////////////////////////////////////////////////////////////////////////////////
+	StatusCode PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout = false);
+	// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
+	//const char *GetStatusCodeName(byte code);
+	static const __FlashStringHelper *GetStatusCodeName(StatusCode code);
+	static PICC_Type PICC_GetType(byte sak);
+	// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
+	//const char *PICC_GetTypeName(byte type);
+	static const __FlashStringHelper *PICC_GetTypeName(PICC_Type type);
+	
+	// Support functions for debuging
+	void PCD_DumpVersionToSerial();
+	void PICC_DumpToSerial(Uid *uid);
+	void PICC_DumpDetailsToSerial(Uid *uid);
+	void PICC_DumpMifareClassicToSerial(Uid *uid, PICC_Type piccType, MIFARE_Key *key);
+	void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
+	void PICC_DumpMifareUltralightToSerial();
+	
+	// Advanced functions for MIFARE
+	void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
+	bool MIFARE_OpenUidBackdoor(bool logErrors);
+	bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors);
+	bool MIFARE_UnbrickUidSector(bool logErrors);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Convenience functions - does not add extra functionality
+	/////////////////////////////////////////////////////////////////////////////////////
+	virtual bool PICC_IsNewCardPresent();
+	virtual bool PICC_ReadCardSerial();
+	
+protected:
+	byte _chipSelectPin;		// Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
+	byte _resetPowerDownPin;	// Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
+	StatusCode MIFARE_TwoStepHelper(byte command, byte blockAddr, int32_t data);
+};
+
+#endif

File diff suppressed because it is too large
+ 1160 - 0
arduinoLibrary/rc522/MFRC522/src/MFRC522Extended.cpp


+ 120 - 0
arduinoLibrary/rc522/MFRC522/src/MFRC522Extended.h

@@ -0,0 +1,120 @@
+/**
+ * Library extends MFRC522.h to support RATS for ISO-14443-4 PICC.
+ * RATS - Request for Answer To Select.
+ * @author JPG-Consulting
+ */
+#ifndef MFRC522Extended_h
+#define MFRC522Extended_h
+
+#include <Arduino.h>
+#include "MFRC522.h"
+
+class MFRC522Extended : public MFRC522 {
+		
+public:
+	// ISO/IEC 14443-4 bit rates
+	enum TagBitRates : byte {
+		BITRATE_106KBITS = 0x00,
+		BITRATE_212KBITS = 0x01,
+		BITRATE_424KBITS = 0x02,
+		BITRATE_848KBITS = 0x03
+	};
+
+	// Structure to store ISO/IEC 14443-4 ATS
+	typedef struct {
+		byte size;
+		byte fsc;                 // Frame size for proximity card
+
+		struct {
+			bool transmitted;
+			bool        sameD;	// Only the same D for both directions supported
+			TagBitRates ds;		// Send D
+			TagBitRates dr;		// Receive D
+		} ta1;
+
+		struct {
+			bool transmitted;
+			byte fwi;			// Frame waiting time integer
+			byte sfgi;			// Start-up frame guard time integer
+		} tb1;
+
+		struct {
+			bool transmitted;
+			bool supportsCID;
+			bool supportsNAD;
+		} tc1;
+
+		// Raw data from ATS
+		byte data[FIFO_SIZE - 2]; // ATS cannot be bigger than FSD - 2 bytes (CRC), according to ISO 14443-4 5.2.2
+	} Ats;
+
+	// A struct used for passing the PICC information
+	typedef struct {
+		uint16_t	atqa;
+		Uid			uid;
+		Ats		    ats; 
+
+		// For Block PCB
+		bool blockNumber;
+	} TagInfo;
+
+	// A struct used for passing PCB Block
+	typedef struct {
+		struct {
+			byte pcb;
+			byte cid;
+			byte nad;
+		} prologue;
+		struct {
+			byte size;
+			byte *data;
+		} inf;
+	} PcbBlock;
+	
+	// Member variables
+	TagInfo tag;
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Contructors
+	/////////////////////////////////////////////////////////////////////////////////////
+	MFRC522Extended() : MFRC522() {};
+	MFRC522Extended(uint8_t rst) : MFRC522(rst) {};
+	MFRC522Extended(uint8_t ss, uint8_t rst) : MFRC522(ss, rst) {};
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for communicating with PICCs
+	/////////////////////////////////////////////////////////////////////////////////////
+	StatusCode PICC_Select(Uid *uid, byte validBits = 0) override; // overrride
+	StatusCode PICC_RequestATS(Ats *ats);
+	StatusCode PICC_PPS();	                                                  // PPS command without bitrate parameter
+	StatusCode PICC_PPS(TagBitRates sendBitRate, TagBitRates receiveBitRate); // Different D values
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Functions for communicating with ISO/IEC 14433-4 cards
+	/////////////////////////////////////////////////////////////////////////////////////
+	StatusCode TCL_Transceive(PcbBlock *send, PcbBlock *back);
+	StatusCode TCL_Transceive(TagInfo * tag, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL);
+	StatusCode TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData = NULL, byte *backLen = NULL);
+	StatusCode TCL_Deselect(TagInfo *tag);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Support functions
+	/////////////////////////////////////////////////////////////////////////////////////
+	static PICC_Type PICC_GetType(TagInfo *tag);
+	using MFRC522::PICC_GetType;// // make old PICC_GetType(byte sak) available, otherwise would be hidden by PICC_GetType(TagInfo *tag)
+
+	// Support functions for debuging
+	void PICC_DumpToSerial(TagInfo *tag);
+	using MFRC522::PICC_DumpToSerial; // make old PICC_DumpToSerial(Uid *uid) available, otherwise would be hidden by PICC_DumpToSerial(TagInfo *tag)
+	void PICC_DumpDetailsToSerial(TagInfo *tag);
+	using MFRC522::PICC_DumpDetailsToSerial; // make old PICC_DumpDetailsToSerial(Uid *uid) available, otherwise would be hidden by PICC_DumpDetailsToSerial(TagInfo *tag)
+	void PICC_DumpISO14443_4(TagInfo *tag);
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Convenience functions - does not add extra functionality
+	/////////////////////////////////////////////////////////////////////////////////////
+	bool PICC_IsNewCardPresent() override; // overrride
+	bool PICC_ReadCardSerial() override; // overrride
+};
+
+#endif

+ 20 - 0
arduinoLibrary/rc522/MFRC522/src/deprecated.h

@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2016 by Ludwig Grill (www.rotzbua.de)
+ * Simple deprecated workaround for Arduino IDE
+ * IDE 1.6.8 use gcc 4.8 which do not support c++14 [[deprecated]]
+ * Later versions should support c++14, then use c++14 syntax
+ */
+#ifndef DEPRECATED_H
+#define DEPRECATED_H
+
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(deprecated)
+#define DEPRECATED [[deprecated]]
+#define DEPRECATED_MSG(msg) [[deprecated(msg)]]
+#endif // __has_cpp_attribute(deprecated)
+#else
+#define DEPRECATED __attribute__((deprecated))
+#define DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#endif // __has_cpp_attribute
+
+#endif // DEPRECATED_H

+ 12 - 0
arduinoLibrary/rc522/MFRC522/src/require_cpp11.h

@@ -0,0 +1,12 @@
+/**
+ * Copyright (c) 2016 by Ludwig Grill (www.rotzbua.de)
+ * Throws error if c++11 is not supported
+ */
+#ifndef REQUIRE_CPP11_H
+#define REQUIRE_CPP11_H
+
+#if __cplusplus < 201103L
+#error "This library needs at least a C++11 compliant compiler, maybe compiler argument for C++11 support is missing or if you use Arduino IDE upgrade to version >=1.6.6"
+#endif
+
+#endif // REQUIRE_CPP11_H

+ 29 - 0
arduinoLibrary/rc522/NDEF_MFRC522/LICENSE

@@ -0,0 +1,29 @@
+Software License Agreement (BSD License)
+
+Copyright (c) 2013-2014, Don Coleman
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holders nor the
+names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 111 - 0
arduinoLibrary/rc522/NDEF_MFRC522/README.md

@@ -0,0 +1,111 @@
+# NDEF Library for Arduino
+
+Read and Write NDEF messages on NFC Tags with Arduino.
+
+NFC Data Exchange Format (NDEF) is a common data format that operates across all NFC devices, regardless of the underlying tag or device technology.
+
+This code works with the cheap MFRC522 tag reader.
+
+### Supports 
+ - Reading from Mifare Classic Tags with 4 byte UIDs.
+ - Writing to Mifare Classic Tags with 4 byte UIDs.
+ - Reading from Mifare Ultralight tags.
+ - Writing to Mifare Ultralight tags.
+
+### Requires
+
+[MFRC522 Library](https://github.com/miguelbalboa/rfid)
+
+## Getting Started
+
+To use the Ndef library in your code, include the following in your sketch:
+
+    #include <SPI.h>
+    #include <MFRC522.h>
+    #include <NfcAdapter.h>
+    
+    MFRC522 mfrc522(CS_PIN, UINT8_MAX);
+    NfcAdapter ndef = NfcAdapter(&mfrc522);
+
+    void setup() {
+        SPI.begin();        // Init SPI bus
+        mfrc522.PCD_Init(); // Init MFRC522
+        nfc.begin();
+    }
+
+### NfcAdapter
+
+The user interacts with the NfcAdapter to read and write NFC tags using the NFC shield.
+
+Read a message from a tag
+
+    if (nfc.tagPresent()) {
+        NfcTag tag = nfc.read();
+        tag.print();
+    }
+
+Write a message to a tag
+
+    if (nfc.tagPresent()) {
+        NdefMessage message = NdefMessage();
+        message.addTextRecord("Hello, Arduino!");
+        success = nfc.write(message);
+    }
+
+Erase a tag. Tags are erased by writing an empty NDEF message. Tags are not zeroed out the old data may still be read off a tag using an application like [NXP's TagInfo](https://play.google.com/store/apps/details?id=com.nxp.taginfolite&hl=en).
+
+    if (nfc.tagPresent()) {
+        success = nfc.erase();
+    }
+
+
+Format a Mifare Classic tag as NDEF.
+
+    if (nfc.tagPresent()) {
+        success = nfc.format();
+    }
+
+
+Clean a tag. Cleaning resets a tag back to a factory-like state. For Mifare Classic, tag is zeroed and reformatted as Mifare Classic (non-NDEF). For Mifare Ultralight, the tag is zeroed and left empty.
+
+    if (nfc.tagPresent()) {
+        success = nfc.clean();
+    }
+
+
+### NfcTag 
+
+Reading a tag with the shield, returns a NfcTag object. The NfcTag object contains meta data about the tag UID, technology, size.  When an NDEF tag is read, the NfcTag object contains a NdefMessage.
+
+### NdefMessage
+
+A NdefMessage consist of one or more NdefRecords.
+
+The NdefMessage object has helper methods for adding records.
+
+    ndefMessage.addTextRecord("hello, world");
+    ndefMessage.addUriRecord("http://arduino.cc");
+
+The NdefMessage object is responsible for encoding NdefMessage into bytes so it can be written to a tag. The NdefMessage also decodes bytes read from a tag back into a NdefMessage object.
+
+### NdefRecord
+
+A NdefRecord carries a payload and info about the payload within a NdefMessage.
+
+### Specifications
+
+This code is based on the "NFC Data Exchange Format (NDEF) Technical Specification" and the "Record Type Definition Technical Specifications" that can be downloaded from the [NFC Forum](http://www.nfc-forum.org/specs/spec_license).
+    
+## Warning
+
+This software is in development. It works for the happy path. Error handling could use improvement. It runs out of memory, especially on the Uno board. Use small messages with the Uno. The Due board can write larger messages. Please submit patches.
+
+## Book
+Need more info? Check out my book <a href="http://www.anrdoezrs.net/click-7521423-11260198-1430755877000?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920021193.do%3Fcmp%3Daf-prog-books-videos-product_cj_9781449372064_%2525zp&cjsku=0636920021193" target="_top">
+Beginning NFC: Near Field Communication with Arduino, Android, and PhoneGap</a><img src="http://www.lduhtrp.net/image-7521423-11260198-1430755877000" width="1" height="1" border="0"/>.
+
+<a href="http://www.tkqlhce.com/click-7521423-11260198-1430755877000?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920021193.do%3Fcmp%3Daf-prog-books-videos-product_cj_9781449372064_%2525zp&cjsku=0636920021193" target="_top"><img src="http://akamaicovers.oreilly.com/images/0636920021193/cat.gif" border="0" alt="Beginning NFC"/></a><img src="http://www.awltovhc.com/image-7521423-11260198-1430755877000" width="1" height="1" border="0"/>
+
+## License
+
+[BSD License](https://github.com/don/Ndef/blob/master/LICENSE.txt) (c) 2013-2014, Don Coleman

+ 35 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/CleanTag/CleanTag.ino

@@ -0,0 +1,35 @@
+// Clean resets a tag back to factory-like state
+// For Mifare Classic, tag is zero'd and reformatted as Mifare Classic
+// For Mifare Ultralight, tags is zero'd and left empty
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup(void) {
+    Serial.begin(9600);
+    Serial.println("NFC Tag Cleaner\nPlace a tag on the NFC reader to clean back to factory state.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop(void) {
+    if (nfc.tagPresent()) {
+        Serial.println("Cleaning tag");
+        bool success = nfc.clean();
+        if (success) {
+            Serial.println("\tSuccess, tag restored to factory state.");
+            delay(10000);
+        } else {
+            Serial.println("\tError, unable to clean tag.");
+        }
+    }
+    delay(5000);
+}

+ 33 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/EraseTag/EraseTag.ino

@@ -0,0 +1,33 @@
+// Erases a NFC tag by writing an empty NDEF message 
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup(void) {
+    Serial.begin(9600);
+    Serial.println("NFC Tag Eraser\nPlace a tag on the NFC reader to erase.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop(void) {
+    if (nfc.tagPresent()) {
+        Serial.println("Erasing tag");
+        bool success = nfc.erase();
+        if (success) {
+            Serial.println("\tSuccess, tag contains an empty record.");        
+            delay(10000);
+        } else {
+            Serial.println("\tUnable to erase tag.");
+        }
+    }
+    delay(5000);
+}

+ 35 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/FormatTag/FormatTag.ino

@@ -0,0 +1,35 @@
+// Formats a Mifare Classic tags as an NDEF tag
+// This will fail if the tag is already formatted NDEF
+// nfc.clean will turn a NDEF formatted Mifare Classic tag back to the Mifare Classic format
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup(void) {
+    Serial.begin(9600);
+    Serial.println("NDEF Formatter\nPlace an unformatted Mifare Classic tag on the reader.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop(void) {
+    if (nfc.tagPresent()) {
+        Serial.println("Formatting tag");
+        bool success = nfc.format();
+        if (success) {
+          Serial.println("\tSuccess, tag formatted as NDEF.");
+          delay(10000);
+        } else {
+          Serial.println("\tFormat failed, card may already be formatted.");
+        }
+    }
+    delay(5000);
+}

+ 30 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/ReadTag/ReadTag.ino

@@ -0,0 +1,30 @@
+// Shows the content of a Mifare Classic tag formatted as an NDEF tag
+// This example requires #define NDEF_USE_SERIAL to be uncommented in Ndef.h
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup(void) {
+    Serial.begin(9600);
+    Serial.println("NDEF Reader\nPlace an unformatted Mifare Classic tag on the reader to show contents.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop(void) {
+    if (nfc.tagPresent())
+    {
+        Serial.println("Reading NFC tag\n");
+        NfcTag tag = nfc.read();
+        tag.print();
+    }
+    delay(5000);
+}

+ 80 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/ReadTagExtended/ReadTagExtended.ino

@@ -0,0 +1,80 @@
+// Shows the content of a Mifare Classic tag formatted as an NDEF tag
+// It serves as an example of how to parse the records one at a time
+// This example requires #define NDEF_USE_SERIAL to be uncommented in Ndef.h
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup(void) {
+    Serial.begin(9600);
+    Serial.println("Extended NDEF Reader\nPlace an unformatted Mifare Classic tag on the reader to show contents.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop(void) {
+    if (nfc.tagPresent())
+    {
+        Serial.println("Reading NFC tag");
+        NfcTag tag = nfc.read();
+        Serial.println(tag.getTagType());
+        Serial.print("UID: ");Serial.println(tag.getUidString());
+    
+        if (tag.hasNdefMessage()) // every tag won't have a message
+        {
+    
+              NdefMessage message = tag.getNdefMessage();
+              Serial.print("\nThis NFC Tag contains an NDEF Message with ");
+              Serial.print(message.getRecordCount());
+              Serial.print(" NDEF Record");
+              if (message.getRecordCount() != 1) {
+                    Serial.print("s");
+              }
+              Serial.println(".");
+        
+              // cycle through the records, printing some info from each
+              int recordCount = message.getRecordCount();
+              for (int i = 0; i < recordCount; i++)
+              {
+                    Serial.print("\nNDEF Record ");Serial.println(i+1);
+                    NdefRecord record = message.getRecord(i);
+                    // NdefRecord record = message[i]; // alternate syntax
+            
+                    Serial.print("  TNF: ");Serial.println(record.getTnf());
+                    Serial.print("  Type: ");PrintHexChar(record.getType(), record.getTypeLength()); // will be "" for TNF_EMPTY
+            
+                    // The TNF and Type should be used to determine how your application processes the payload
+                    // There's no generic processing for the payload, it's returned as a byte[]
+                    int payloadLength = record.getPayloadLength();
+                    const byte *payload = record.getPayload();
+            
+                    // Print the Hex and Printable Characters
+                    Serial.print("  Payload (HEX): ");
+                    PrintHexChar(payload, payloadLength);
+            
+                    // Force the data into a String (might work depending on the content)
+                    // Real code should use smarter processing
+                    String payloadAsString = "";
+                    for (int c = 0; c < payloadLength; c++) {
+                          payloadAsString += (char)payload[c];
+                    }
+                    Serial.print("  Payload (as String): ");
+                    Serial.println(payloadAsString);
+            
+                    // id is probably blank and will return ""
+                    if (record.getIdLength() > 0) {
+                          Serial.print("  ID: ");PrintHexChar(record.getId(), record.getIdLength());
+                    }
+              }
+        }
+  }
+  delay(5000);
+}

+ 35 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/WriteTag/WriteTag.ino

@@ -0,0 +1,35 @@
+// Writes a single URI record (https://arduino.cc) to an NFC formatted tag. Note this erases all existing records.
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup() {
+    Serial.begin(9600);
+    Serial.println("NDEF writer\nPlace a formatted Mifare Classic or Ultralight NFC tag on the reader.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop() {
+    if (nfc.tagPresent()) {
+        Serial.println("Writing record to NFC tag");
+        NdefMessage message = NdefMessage();
+        message.addUriRecord("https://arduino.cc");
+        bool success = nfc.write(message);
+        if (success) {
+          Serial.println("\tSuccess. Try reading this tag with your phone.");        
+          delay(10000);
+        } else {
+          Serial.println("\tWrite failed.");
+        }
+    }
+    delay(5000);
+}

+ 37 - 0
arduinoLibrary/rc522/NDEF_MFRC522/examples/WriteTagMultipleRecords/WriteTagMultipleRecords.ino

@@ -0,0 +1,37 @@
+// Writes multiple records to an NFC formatted tag. Note this erases all existing records.
+
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+#define CS_PIN 10
+
+MFRC522 mfrc522(CS_PIN, UINT8_MAX); // Create MFRC522 instance
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void setup() {
+    Serial.begin(9600);
+    Serial.println("NDEF multiple record writer\nPlace a formatted Mifare Classic or Ultralight NFC tag on the reader.");
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void loop() {
+    if (nfc.tagPresent()) {
+        Serial.println("Writing multiple records to NFC tag");
+        NdefMessage message = NdefMessage();
+        message.addTextRecord("Hello, Arduino!");
+        message.addUriRecord("https://arduino.cc");
+        message.addTextRecord("Goodbye, Arduino!");
+        boolean success = nfc.write(message);
+        if (success) {
+            Serial.println("\tSuccess. Try reading this tag with your phone.");
+            delay(10000);
+        } else {
+            Serial.println("\tWrite failed");
+        }
+    }
+    delay(5000);
+}

+ 61 - 0
arduinoLibrary/rc522/NDEF_MFRC522/keywords.txt

@@ -0,0 +1,61 @@
+#######################################
+# Syntax Coloring Map For Ndef
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+MifareClassic	KEYWORD1
+MifareUltralight	KEYWORD1
+NdefMessage	KEYWORD1
+NdefRecord	KEYWORD1
+NfcAdapter	KEYWORD1
+NfcDriver	KEYWORD1
+NfcTag	KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+addEmptyRecord	KEYWORD2
+addExternalRecord	KEYWORD2
+addMimeMediaRecord	KEYWORD2
+addRecord	KEYWORD2
+addTextRecord	KEYWORD2
+addUriRecord	KEYWORD2
+begin	KEYWORD2
+clean	KEYWORD2
+encode	KEYWORD2
+erase	KEYWORD2
+format	KEYWORD2
+formatNDEF	KEYWORD2
+formatMifare	KEYWORD2
+getEncodedSize	KEYWORD2
+getId	KEYWORD2
+getIdLength	KEYWORD2
+getNdefMessage	KEYWORD2
+getPayload	KEYWORD2
+getPayloadLength	KEYWORD2
+getRecord	KEYWORD2
+getRecordCount	KEYWORD2
+getTagType	KEYWORD2
+getTnf	KEYWORD2
+getType	KEYWORD2
+getTypeLength	KEYWORD2
+getUid	KEYWORD2
+getUidLength	KEYWORD2
+getUidString	KEYWORD2
+haltTag	KEYWORD2
+hasNdefMessage	KEYWORD2
+isFormatted	KEYWORD2
+print	KEYWORD2
+read	KEYWORD2
+setId	KEYWORD2
+setPayload	KEYWORD2
+setTnf	KEYWORD2
+setType	KEYWORD2
+share	KEYWORD2
+tagPresent	KEYWORD2
+unshare	KEYWORD2
+write	KEYWORD2

+ 32 - 0
arduinoLibrary/rc522/NDEF_MFRC522/library.json

@@ -0,0 +1,32 @@
+{
+  "name": "NDEF_MFRC522",
+  "version": "2.0.1",
+  "description": "Read and write NDEF messages to NFC tags and peers. Ported to the MFRC522 reader.",
+  "keywords": "ndef, mfrc522, rfid",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/TheNitek/NDEF.git"
+  },
+  "authors":
+  [
+    {
+      "name": "Don Coleman",
+      "email": "don.coleman@gmail.com",
+      "url": "https://github.com/don"
+    },
+    {
+      "name": "Claus Näveke",
+      "email": "github@naeveke.de",
+      "url": "https://github.com/TheNitek",
+      "maintainer": true
+    }
+  ],
+  "license": "BSD-3-Clause",
+  "homepage": "https://github.com/TheNitek/NDEF",
+  "dependencies": {
+    "miguelbalboa/MFRC522": "~1.4.7"
+  },
+  "frameworks": ["Arduino"],
+  "platforms": ["atmelavr", "ststm32", "espressif8266", "espressif32", "atmelsam"]
+}

+ 11 - 0
arduinoLibrary/rc522/NDEF_MFRC522/library.properties

@@ -0,0 +1,11 @@
+name=NDEF_MFRC522
+version=2.0.1
+author=Don Coleman <don.coleman@gmail.com>
+maintainer=Claus Näveke <github@naeveke.de>
+sentence=An Arduino library for NFC Data Exchange Format (NDEF).
+paragraph=Read and write NDEF messages to NFC tags and peers. Supports the MFRC522 reader. This library depends on the MFRC522 library https://github.com/miguelbalboa/rfid.
+category=Communication
+url=https://github.com/TheNitek/NDEF
+depends=MFRC522
+architectures=avr,megaavr,STM32F1,teensy,esp8266,esp32,samd
+includes=NfcAdapter.h

+ 25 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/Due.h

@@ -0,0 +1,25 @@
+// redefine some stuff so code works on Due
+// http://arduino.cc/forum/index.php?&topic=153761.0
+
+#ifndef Due_h
+#define Due_h
+
+#if defined(__SAM3X8E__)
+    #define PROGMEM
+    #define pgm_read_byte(x)        (*((char *)x))
+//  #define pgm_read_word(x)        (*((short *)(x & 0xfffffffe)))
+    #define pgm_read_word(x)        ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
+    #define pgm_read_byte_near(x)   (*((char *)x))
+    #define pgm_read_byte_far(x)    (*((char *)x))
+//  #define pgm_read_word_near(x)   (*((short *)(x & 0xfffffffe))
+//  #define pgm_read_word_far(x)    (*((short *)(x & 0xfffffffe)))
+    #define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
+    #define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
+    #define PSTR(x)  x
+  #if defined F
+    #undef F
+  #endif
+  #define F(X) (X)
+#endif
+
+#endif

+ 456 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/MifareClassic.cpp

@@ -0,0 +1,456 @@
+#include "MifareClassic.h"
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+
+MifareClassic::MifareClassic(MFRC522 *nfcShield)
+{
+  _nfcShield = nfcShield;
+}
+
+MifareClassic::~MifareClassic()
+{
+}
+
+NfcTag MifareClassic::read()
+{
+    MFRC522::MIFARE_Key key = {{0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}};
+    int messageStartIndex = 0;
+    int messageLength = 0;
+    byte dataSize = BLOCK_SIZE + 2;
+    byte data[dataSize];
+
+    // read first block to get message length
+    if (_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(_nfcShield->uid)) == MFRC522::STATUS_OK)
+    {
+        if(_nfcShield->MIFARE_Read(4, data, &dataSize) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.println(F("Error. Failed read block 4"));
+#endif
+            return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_MIFARE_CLASSIC);
+        }
+
+        if (!decodeTlv(data, &messageLength, &messageStartIndex))
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.println(F("Error. Could not decode TLV"));
+#endif
+            return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_UNKNOWN); // TODO should the error message go in NfcTag?
+        }
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Tag is not NDEF formatted."));
+#endif
+        return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_MIFARE_CLASSIC, false);
+    }
+
+    int currentBlock = 4;
+    // this should be nested in the message length loop
+    int index = 0;
+    // Add 2 to allow MFRC522 to add CRC
+    int bufferSize = getBufferSize(messageLength) + 2;
+    uint8_t buffer[bufferSize];
+
+    #ifdef MIFARE_CLASSIC_DEBUG
+    Serial.print(F("Message Length "));Serial.println(messageLength);
+    Serial.print(F("Buffer Size "));Serial.println(bufferSize);
+    #endif
+
+    while (index < bufferSize-2)
+    {
+
+        // authenticate on every sector
+        if (((currentBlock < 128) && (currentBlock % 4 == 0)) || ((currentBlock >= 128) && (currentBlock % 16 == 0)))
+        {
+
+            if (_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, currentBlock, &key, &(_nfcShield->uid)) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Error. Block Authentication failed for "));Serial.println(currentBlock);
+#endif
+                // TODO Nicer error handling
+                return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_MIFARE_CLASSIC);
+            }
+        }
+
+        // read the data
+        byte readBufferSize = 18;
+        if(_nfcShield->MIFARE_Read(currentBlock, &buffer[index], &readBufferSize) == MFRC522::STATUS_OK)
+        {
+            #ifdef MIFARE_CLASSIC_DEBUG
+            Serial.print(F("Block "));Serial.print(currentBlock);Serial.print(" ");
+            PrintHexChar(&buffer[index], BLOCK_SIZE);
+            #endif
+        }
+        else
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Read failed "));Serial.println(currentBlock);
+#endif
+            // TODO Nicer error handling
+            return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_MIFARE_CLASSIC);
+        }
+
+        index += BLOCK_SIZE;
+        currentBlock++;
+
+        // skip the trailer block
+        if (((currentBlock < 128) && ((currentBlock+1) % 4 == 0)) || ((currentBlock >= 128) && ((currentBlock+1) % 16 == 0)))
+        {
+            #ifdef MIFARE_CLASSIC_DEBUG
+            Serial.print(F("Skipping block "));Serial.println(currentBlock);
+            #endif
+            currentBlock++;
+        }
+    }
+
+    return NfcTag(_nfcShield->uid.uidByte, _nfcShield->uid.size, NfcTag::TYPE_MIFARE_CLASSIC, &buffer[messageStartIndex], messageLength);
+}
+
+int MifareClassic::getBufferSize(int messageLength)
+{
+
+    int bufferSize = messageLength;
+
+    // TLV header is 2 or 4 bytes, TLV terminator is 1 byte.
+    if (messageLength < 0xFF)
+    {
+        bufferSize += SHORT_TLV_SIZE + 1;
+    }
+    else
+    {
+        bufferSize += LONG_TLV_SIZE + 1;
+    }
+
+    // bufferSize needs to be a multiple of BLOCK_SIZE
+    if (bufferSize % BLOCK_SIZE != 0)
+    {
+        bufferSize = ((bufferSize / BLOCK_SIZE) + 1) * BLOCK_SIZE;
+    }
+
+    return bufferSize;
+}
+
+// skip null tlvs (0x0) before the real message
+// technically unlimited null tlvs, but we assume
+// T & L of TLV in the first block we read
+int MifareClassic::getNdefStartIndex(byte *data)
+{
+
+    for (int i = 0; i < BLOCK_SIZE; i++)
+    {
+        if (data[i] == 0x0)
+        {
+            // do nothing, skip
+        }
+        else if (data[i] == 0x3)
+        {
+            return i;
+        }
+        else
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print("Unknown TLV ");Serial.println(data[i], HEX);
+#endif
+            return -2;
+        }
+    }
+
+    return -1;
+}
+
+// Decode the NDEF data length from the Mifare TLV
+// Leading null TLVs (0x0) are skipped
+// Assuming T & L of TLV will be in the first block
+// messageLength and messageStartIndex written to the parameters
+// success or failure status is returned
+//
+// { 0x3, LENGTH }
+// { 0x3, 0xFF, LENGTH, LENGTH }
+bool MifareClassic::decodeTlv(byte *data, int *messageLength, int *messageStartIndex)
+{
+    int i = getNdefStartIndex(data);
+
+    if (i < 0 || data[i] != 0x3)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Error. Can't decode message length."));
+#endif
+        return false;
+    }
+    else
+    {
+        if (data[i+1] == 0xFF)
+        {
+            *messageLength = ((0xFF & data[i+2]) << 8) | (0xFF & data[i+3]);
+            *messageStartIndex = i + LONG_TLV_SIZE;
+        }
+        else
+        {
+            *messageLength = data[i+1];
+            *messageStartIndex = i + SHORT_TLV_SIZE;
+        }
+    }
+
+    return true;
+}
+
+// Intialized NDEF tag contains one empty NDEF TLV 03 00 FE - AN1304 6.3.1
+// We are formatting in read/write mode with a NDEF TLV 03 03 and an empty NDEF record D0 00 00 FE - AN1304 6.3.2
+bool MifareClassic::formatNDEF()
+{
+    MFRC522::MIFARE_Key keya = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+    byte emptyNdefMesg[16] = {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    byte blockbuffer0[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    byte blockbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
+    byte blockbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
+    byte blockbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+    byte blockbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+    // TODO use UID from method parameters?
+    if (_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &keya, &(_nfcShield->uid)) != MFRC522::STATUS_OK)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Unable to authenticate block 1 to enable card formatting!"));
+#endif
+        return false;
+    }
+
+    if (_nfcShield->MIFARE_Write(1, blockbuffer1, 16) != MFRC522::STATUS_OK)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Unable to format the card for NDEF: Block 1 failed"));
+#endif
+        return false;
+    }
+
+    if (_nfcShield->MIFARE_Write(2, blockbuffer2, 16) != MFRC522::STATUS_OK)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Unable to format the card for NDEF: Block 2 failed"));
+#endif
+        return false;
+    }
+    // Write new key A and permissions
+    if (_nfcShield->MIFARE_Write(3, blockbuffer3, 16) != MFRC522::STATUS_OK)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("Unable to format the card for NDEF: Block 3 failed"));
+#endif
+        return false;
+    }
+    for (int i=4; i<64; i+=4) {
+        if (_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, i, &keya, &(_nfcShield->uid)) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+                    Serial.print(F("Unable to authenticate block "));Serial.println(i);
+#endif
+            return false;
+        }
+
+        if (i == 4)  // special handling for block 4
+        {
+            if (_nfcShield->MIFARE_Write(i, emptyNdefMesg, 16) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Unable to write block "));Serial.println(i);
+#endif
+                return false;
+            }
+        }
+        else
+        {
+            if (_nfcShield->MIFARE_Write(i, blockbuffer0, 16) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Unable to write block "));Serial.println(i);
+#endif
+                return false;
+            }
+        }
+        if (_nfcShield->MIFARE_Write(i+1, blockbuffer0, 16) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Unable to write block "));Serial.println(i+1);
+#endif
+            return false;
+        }
+        if (_nfcShield->MIFARE_Write(i+2, blockbuffer0, 16) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Unable to write block "));Serial.println(i+2);
+#endif
+            return false;
+        }
+        if (_nfcShield->MIFARE_Write(i+3, blockbuffer4, 16) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Unable to write block "));Serial.println(i+3);
+#endif
+            return false;
+        }
+    }
+    return true;
+}
+
+#define NR_SHORTSECTOR          (32)    // Number of short sectors on Mifare 1K/4K
+#define NR_LONGSECTOR           (8)     // Number of long sectors on Mifare 4K
+#define NR_BLOCK_OF_SHORTSECTOR (4)     // Number of blocks in a short sector
+#define NR_BLOCK_OF_LONGSECTOR  (16)    // Number of blocks in a long sector
+
+// Determine the sector trailer block based on sector number
+#define BLOCK_NUMBER_OF_SECTOR_TRAILER(sector) (((sector)<NR_SHORTSECTOR)? \
+  ((sector)*NR_BLOCK_OF_SHORTSECTOR + NR_BLOCK_OF_SHORTSECTOR-1):\
+  (NR_SHORTSECTOR*NR_BLOCK_OF_SHORTSECTOR + (sector-NR_SHORTSECTOR)*NR_BLOCK_OF_LONGSECTOR + NR_BLOCK_OF_LONGSECTOR-1))
+
+bool MifareClassic::formatMifare()
+{
+
+    // The default Mifare Classic key
+    MFRC522::MIFARE_Key KEY_DEFAULT_KEYAB = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+    byte emptyBlock[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    byte authBlock[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+
+    uint8_t idx = 0;
+    uint8_t numOfSector = 16;                         // Assume Mifare Classic 1K for now (16 4-block sectors)
+
+    for (idx = 0; idx < numOfSector; idx++)
+    {
+        // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
+        if (_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), &KEY_DEFAULT_KEYAB, &(_nfcShield->uid)) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Authentication failed for sector ")); Serial.println(idx);
+#endif
+            return false;
+        }
+
+        // Step 2: Write to the other blocks
+        if (idx == 0)
+        {
+            if (_nfcShield->MIFARE_Write((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, emptyBlock, 16) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Unable to write to sector ")); Serial.println(idx);
+#endif
+            }
+        }
+        else
+        {
+            // this block has not to be overwritten for block 0. It contains Tag id and other unique data.
+            if (_nfcShield->MIFARE_Write((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, emptyBlock, 16) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Unable to write to sector ")); Serial.println(idx);
+#endif
+            }
+            if (_nfcShield->MIFARE_Write((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, emptyBlock, 16) != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Unable to write to sector ")); Serial.println(idx);
+#endif
+            }
+        }
+
+        if (_nfcShield->MIFARE_Write((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, emptyBlock, 16) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Unable to write to sector ")); Serial.println(idx);
+#endif
+        }
+
+        // Write the trailer block
+        if (_nfcShield->MIFARE_Write((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), authBlock, 16) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Unable to write trailer block of sector ")); Serial.println(idx);
+#endif
+        }
+    }
+    return true;
+}
+
+bool MifareClassic::write(NdefMessage& m)
+{
+
+    uint8_t encoded[m.getEncodedSize()];
+    m.encode(encoded);
+
+    uint8_t buffer[getBufferSize(sizeof(encoded))];
+    memset(buffer, 0, sizeof(buffer));
+
+    #ifdef MIFARE_CLASSIC_DEBUG
+    Serial.print(F("sizeof(encoded) "));Serial.println(sizeof(encoded));
+    Serial.print(F("sizeof(buffer) "));Serial.println(sizeof(buffer));
+    #endif
+
+    if (sizeof(encoded) < 0xFF)
+    {
+        buffer[0] = 0x3;
+        buffer[1] = sizeof(encoded);
+        memcpy(&buffer[2], encoded, sizeof(encoded));
+        buffer[2+sizeof(encoded)] = 0xFE; // terminator
+    }
+    else
+    {
+        buffer[0] = 0x3;
+        buffer[1] = 0xFF;
+        buffer[2] = ((sizeof(encoded) >> 8) & 0xFF);
+        buffer[3] = (sizeof(encoded) & 0xFF);
+        memcpy(&buffer[4], encoded, sizeof(encoded));
+        buffer[4+sizeof(encoded)] = 0xFE; // terminator
+    }
+
+    // Write to tag
+    unsigned int index = 0;
+    byte currentBlock = 4;
+    MFRC522::MIFARE_Key key = {{0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}};
+
+    while (index < sizeof(buffer))
+    {
+
+        if (((currentBlock < 128) && (currentBlock % 4 == 0)) || ((currentBlock >= 128) && (currentBlock % 16 == 0)))
+        {
+            MFRC522::StatusCode status =_nfcShield->PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, currentBlock, &key, &(_nfcShield->uid));
+            if (status != MFRC522::STATUS_OK)
+            {
+#ifdef NDEF_USE_SERIAL
+                Serial.print(F("Error. Block authentication failed for block "));Serial.println(currentBlock);
+                Serial.print(_nfcShield->GetStatusCodeName(status));
+#endif
+                return false;
+            }
+        }
+
+        if (_nfcShield->MIFARE_Write(currentBlock, &buffer[index], BLOCK_SIZE) != MFRC522::STATUS_OK)
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Write failed "));Serial.println(currentBlock);
+#endif
+            return false;
+        }
+
+        #ifdef MIFARE_CLASSIC_DEBUG
+        Serial.print(F("Wrote block "));Serial.print(currentBlock);Serial.print(" - ");
+        PrintHexChar(&buffer[index], BLOCK_SIZE);
+        #endif
+
+        index += BLOCK_SIZE;
+        currentBlock++;
+
+        if (((currentBlock < 128) && ((currentBlock+1) % 4 == 0)) || ((currentBlock >= 128) && ((currentBlock+1) % 16 == 0)))
+        {
+            // can't write to trailer block
+            #ifdef MIFARE_CLASSIC_DEBUG
+            Serial.print(F("Skipping block "));Serial.println(currentBlock);
+            #endif
+            currentBlock++;
+        }
+
+    }
+
+    return true;
+}
+#endif

+ 37 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/MifareClassic.h

@@ -0,0 +1,37 @@
+#ifndef MifareClassic_h
+#define MifareClassic_h
+
+// Comment out next line to remove Mifare Classic and save memory
+#define NDEF_SUPPORT_MIFARE_CLASSIC
+
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+
+//#define MIFARE_CLASSIC_DEBUG 1
+
+#define BLOCK_SIZE 16
+#define LONG_TLV_SIZE 4
+#define SHORT_TLV_SIZE 2
+
+#include <Due.h>
+#include <MFRC522.h>
+#include <Ndef.h>
+#include <NfcTag.h>
+
+class MifareClassic
+{
+    public:
+        MifareClassic(MFRC522 *nfcShield);
+        ~MifareClassic();
+        NfcTag read();
+        bool write(NdefMessage& ndefMessage);
+        bool formatNDEF();
+        bool formatMifare();
+    private:
+        MFRC522* _nfcShield;
+        int getBufferSize(int messageLength);
+        int getNdefStartIndex(byte *data);
+        bool decodeTlv(byte *data, int *messageLength, int *messageStartIndex);
+};
+
+#endif
+#endif

+ 258 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/MifareUltralight.cpp

@@ -0,0 +1,258 @@
+#include <MifareUltralight.h>
+
+MifareUltralight::MifareUltralight(MFRC522 *nfcShield)
+{
+    nfc = nfcShield;
+}
+
+MifareUltralight::~MifareUltralight()
+{
+}
+
+NfcTag MifareUltralight::read()
+{
+    if (isUnformatted())
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("WARNING: Tag is not formatted."));
+#endif
+        return NfcTag(nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_2);
+    }
+
+    uint16_t messageLength = 0;
+    uint16_t ndefStartIndex = 0;
+    findNdefMessage(&messageLength, &ndefStartIndex);
+
+    uint16_t bufferSize = calculateBufferSize(messageLength, ndefStartIndex);
+
+    if (messageLength == 0) { // data is 0x44 0x03 0x00 0xFE
+        NdefMessage message = NdefMessage();
+        message.addEmptyRecord();
+        return NfcTag(nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_2, message);
+    }
+
+    uint8_t index = 0;
+    byte buffer[bufferSize];
+    for (uint8_t page = ULTRALIGHT_DATA_START_PAGE; page < ULTRALIGHT_MAX_PAGE; page+=(ULTRALIGHT_READ_SIZE/ULTRALIGHT_PAGE_SIZE))
+    {
+        // read the data
+        byte dataSize = ULTRALIGHT_READ_SIZE + 2;
+        MFRC522::StatusCode status = nfc->MIFARE_Read(page, &buffer[index], &dataSize);
+        if (status == MFRC522::STATUS_OK)
+        {
+            #ifdef MIFARE_ULTRALIGHT_DEBUG
+            Serial.print(F("Page "));Serial.print(page);Serial.print(" ");
+            PrintHexChar(&buffer[index], ULTRALIGHT_PAGE_SIZE);
+            PrintHexChar(&buffer[index+ULTRALIGHT_PAGE_SIZE], ULTRALIGHT_PAGE_SIZE);
+            PrintHexChar(&buffer[index+2*ULTRALIGHT_PAGE_SIZE], ULTRALIGHT_PAGE_SIZE);
+            PrintHexChar(&buffer[index+3*ULTRALIGHT_PAGE_SIZE], ULTRALIGHT_PAGE_SIZE);
+            #endif
+        }
+        else
+        {
+#ifdef NDEF_USE_SERIAL
+            Serial.print(F("Read failed "));Serial.println(page);
+#endif
+            return NfcTag(nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_2);
+        }
+
+        if (index >= (messageLength + ndefStartIndex))
+        {
+            break;
+        }
+
+        index += ULTRALIGHT_READ_SIZE;
+    }
+
+    return NfcTag(nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_2, &buffer[ndefStartIndex], messageLength);
+
+}
+
+boolean MifareUltralight::isUnformatted()
+{
+    uint8_t page = 4;
+    byte dataSize = ULTRALIGHT_READ_SIZE+2;
+    byte data[dataSize];
+    MFRC522::StatusCode status = nfc->MIFARE_Read(page, data, &dataSize);
+    if (status == MFRC522::STATUS_OK && dataSize >= 4)
+    {
+        return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF);
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("Error. Failed read page "));Serial.println(page);
+#endif
+        return false;
+    }
+}
+
+// page 3 has tag capabilities
+uint16_t MifareUltralight::readTagSize()
+{
+    uint16_t tagCapacity = 0;
+    byte dataSize = ULTRALIGHT_READ_SIZE+2;
+    byte data[dataSize];
+    MFRC522::StatusCode status = nfc->MIFARE_Read(3, data, &dataSize);
+    if (status == MFRC522::STATUS_OK && dataSize >= 2)
+    {
+        // See AN1303 - different rules for Mifare Family byte2 = (additional data + 48)/8
+        tagCapacity = data[2] * 8;
+        #ifdef MIFARE_ULTRALIGHT_DEBUG
+        Serial.print(F("Tag capacity "));Serial.print(tagCapacity);Serial.println(F(" bytes"));
+        #endif
+
+        // TODO future versions should get lock information
+    }
+
+    return tagCapacity;
+}
+
+// read enough of the message to find the ndef message length
+void MifareUltralight::findNdefMessage(uint16_t *messageLength, uint16_t *ndefStartIndex)
+{
+    byte dataSize = ULTRALIGHT_READ_SIZE + 2;
+    byte data[dataSize]; // 3 pages, but 4 + CRC are returned
+
+    if(nfc->MIFARE_Read(4, data, &dataSize) == MFRC522::STATUS_OK)
+    {
+        #ifdef MIFARE_ULTRALIGHT_DEBUG
+        Serial.println(F("Pages 4-7"));
+        PrintHexChar(data, 18);
+        PrintHexChar(data+ULTRALIGHT_PAGE_SIZE, 18);
+        PrintHexChar(data+2*ULTRALIGHT_PAGE_SIZE, 18);
+        PrintHexChar(data+3*ULTRALIGHT_PAGE_SIZE, 18);
+        #endif
+
+        if (data[0] == 0x03)
+        {
+            *messageLength = data[1];
+            *ndefStartIndex = 2;
+        }
+        else if (data[5] == 0x3) // page 5 byte 1
+        {
+            // TODO should really read the lock control TLV to ensure byte[5] is correct
+            *messageLength = data[6];
+            *ndefStartIndex = 7;
+        }
+    }
+
+    #ifdef MIFARE_ULTRALIGHT_DEBUG
+    Serial.print(F("messageLength "));Serial.println(*messageLength);
+    Serial.print(F("ndefStartIndex "));Serial.println(*ndefStartIndex);
+    #endif
+}
+
+// buffer is larger than the message, need to handle some data before and after
+// message and need to ensure we read full pages
+uint16_t MifareUltralight::calculateBufferSize(uint16_t messageLength, uint16_t ndefStartIndex)
+{
+    // TLV terminator 0xFE is 1 byte
+    uint16_t bufferSize = messageLength + ndefStartIndex + 1;
+
+    if (bufferSize % ULTRALIGHT_READ_SIZE != 0)
+    {
+        // buffer must be an increment of page size
+        bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE;
+    }
+
+    //MFRC522 also return CRC
+    bufferSize += 2;
+
+    return bufferSize;
+}
+
+boolean MifareUltralight::write(NdefMessage& m)
+{
+    if (isUnformatted())
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("WARNING: Tag is not formatted."));
+#endif
+        return false;
+    }
+    uint16_t tagCapacity = readTagSize(); // meta info for tag
+
+    uint16_t messageLength  = m.getEncodedSize();
+    uint16_t ndefStartIndex = messageLength < 0xFF ? 2 : 4;
+    uint16_t bufferSize = calculateBufferSize(messageLength, ndefStartIndex);
+
+    if(bufferSize>tagCapacity) {
+	    #ifdef MIFARE_ULTRALIGHT_DEBUG
+    	Serial.print(F("Encoded Message length exceeded tag Capacity "));Serial.println(tagCapacity);
+    	#endif
+    	return false;
+    }
+
+    uint8_t encoded[bufferSize];
+    uint8_t *  src = encoded;
+    unsigned int position = 0;
+    uint8_t page = ULTRALIGHT_DATA_START_PAGE;
+
+    // Set message size. With ultralight should always be less than 0xFF but who knows?
+
+    encoded[0] = 0x3;
+    if (messageLength < 0xFF)
+    {
+        encoded[1] = messageLength;
+    }
+    else
+    {
+        encoded[1] = 0xFF;
+        encoded[2] = ((messageLength >> 8) & 0xFF);
+        encoded[3] = (messageLength & 0xFF);
+    }
+
+    m.encode(encoded+ndefStartIndex);
+    // this is always at least 1 byte copy because of terminator.
+    memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength);
+    encoded[ndefStartIndex+messageLength] = 0xFE; // terminator
+
+    #ifdef MIFARE_ULTRALIGHT_DEBUG
+    Serial.print(F("messageLength "));Serial.println(messageLength);
+    Serial.print(F("Tag Capacity "));Serial.println(tagCapacity);
+    PrintHex(encoded,bufferSize);
+    #endif
+
+    while (position < bufferSize){ //bufferSize is always times pagesize so no "last chunk" check
+        // Although we have to provide 16 bytes to MIFARE_Write only 4 of them are written onto the tag
+        byte writeBuffer[16] = {0};
+        memcpy (writeBuffer, src, 4);
+        // write page
+        if (nfc->MIFARE_Write(page, writeBuffer, 16) != MFRC522::STATUS_OK)
+            return false;
+		#ifdef MIFARE_ULTRALIGHT_DEBUG
+        Serial.print(F("Wrote page "));Serial.print(page);Serial.print(F(" - "));
+    	PrintHex(src,ULTRALIGHT_PAGE_SIZE);
+    	#endif
+        page++;
+        src+=ULTRALIGHT_PAGE_SIZE;
+        position+=ULTRALIGHT_PAGE_SIZE;
+    }
+    return true;
+}
+
+// Mifare Ultralight can't be reset to factory state
+// zero out tag data like the NXP Tag Write Android application
+boolean MifareUltralight::clean()
+{
+    uint16_t tagCapacity = readTagSize();
+
+    uint8_t pages = (tagCapacity / ULTRALIGHT_PAGE_SIZE) + ULTRALIGHT_DATA_START_PAGE;
+
+    // factory tags have 0xFF, but OTP-CC blocks have already been set so we use 0x00
+    byte data[16] = { 0 };
+
+    for (int i = ULTRALIGHT_DATA_START_PAGE; i < pages; i++)
+    {
+        #ifdef MIFARE_ULTRALIGHT_DEBUG
+        Serial.print(F("Wrote page "));Serial.print(i);Serial.print(F(" - "));
+        PrintHex(data, ULTRALIGHT_PAGE_SIZE);
+        #endif
+        if (nfc->MIFARE_Write(i, data, 16) != MFRC522::STATUS_OK)
+        {
+            return false;
+        }
+    }
+    return true;
+}

+ 34 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/MifareUltralight.h

@@ -0,0 +1,34 @@
+#ifndef MifareUltralight_h
+#define MifareUltralight_h
+
+#include <MFRC522.h>
+#include <NfcTag.h>
+#include <Ndef.h>
+
+//#define MIFARE_ULTRALIGHT_DEBUG 1
+
+#define ULTRALIGHT_PAGE_SIZE 4
+#define ULTRALIGHT_READ_SIZE 16
+
+#define ULTRALIGHT_DATA_START_PAGE 4
+#define ULTRALIGHT_MESSAGE_LENGTH_INDEX 1
+#define ULTRALIGHT_DATA_START_INDEX 2
+#define ULTRALIGHT_MAX_PAGE 63
+
+class MifareUltralight
+{
+    public:
+        MifareUltralight(MFRC522 *nfcShield);
+        ~MifareUltralight();
+        NfcTag read();
+        boolean write(NdefMessage& ndefMessage);
+        boolean clean();
+    private:
+        MFRC522 *nfc;
+        boolean isUnformatted();
+        uint16_t readTagSize();
+        void findNdefMessage(uint16_t *messageLength, uint16_t *ndefStartIndex);
+        uint16_t calculateBufferSize(uint16_t messageLength, uint16_t ndefStartIndex);
+};
+
+#endif

+ 59 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/Ndef.cpp

@@ -0,0 +1,59 @@
+#include "Ndef.h"
+
+#ifdef NDEF_USE_SERIAL
+// Borrowed from Adafruit_NFCShield_I2C
+void PrintHex(const byte * data, const long numBytes)
+{
+  int32_t szPos;
+  for (szPos=0; szPos < numBytes; szPos++)
+  {
+    Serial.print("0x");
+    // Append leading 0 for small values
+    if (data[szPos] <= 0xF)
+      Serial.print("0");
+    Serial.print(data[szPos]&0xff, HEX);
+    if ((numBytes > 1) && (szPos != numBytes - 1))
+    {
+      Serial.print(" ");
+    }
+  }
+  Serial.println("");
+}
+
+// Borrowed from Adafruit_NFCShield_I2C
+void PrintHexChar(const byte * data, const long numBytes)
+{
+  int32_t szPos;
+  for (szPos=0; szPos < numBytes; szPos++)
+  {
+    // Append leading 0 for small values
+    if (data[szPos] <= 0xF)
+      Serial.print("0");
+    Serial.print(data[szPos], HEX);
+    if ((numBytes > 1) && (szPos != numBytes - 1))
+    {
+      Serial.print(" ");
+    }
+  }
+  Serial.print("  ");
+  for (szPos=0; szPos < numBytes; szPos++)
+  {
+    if (data[szPos] <= 0x1F)
+      Serial.print(".");
+    else
+      Serial.print((char)data[szPos]);
+  }
+  Serial.println("");
+}
+
+// Note if buffer % blockSize != 0, last block will not be written
+void DumpHex(const byte * data, const unsigned long numBytes, const unsigned int blockSize)
+{
+    unsigned int i;
+    for (i = 0; i < (numBytes / blockSize); i++)
+    {
+        PrintHexChar(data, blockSize);
+        data += blockSize;
+    }
+}
+#endif

+ 19 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/Ndef.h

@@ -0,0 +1,19 @@
+#ifndef Ndef_h
+#define Ndef_h
+
+// To save memory and stop serial output comment out the next line
+//#define NDEF_USE_SERIAL
+
+/* NOTE: To use the Ndef library in your code, don't include Ndef.h
+   See README.md for details on which files to include in your sketch.
+*/
+
+#include <Arduino.h>
+
+#ifdef NDEF_USE_SERIAL
+void PrintHex(const byte *data, const long numBytes);
+void PrintHexChar(const byte *data, const long numBytes);
+void DumpHex(const byte *data, const long numBytes, const int blockSize);
+#endif
+
+#endif

+ 277 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NdefMessage.cpp

@@ -0,0 +1,277 @@
+#include <NdefMessage.h>
+
+NdefMessage::NdefMessage(void)
+{
+    _recordCount = 0;
+}
+
+NdefMessage::NdefMessage(const byte * data, const uint16_t numBytes)
+{
+#ifdef NDEF_USE_SERIAL
+    Serial.print(F("Decoding "));Serial.print(numBytes);Serial.println(F(" bytes"));
+    PrintHexChar(data, numBytes);
+#endif
+
+    _recordCount = 0;
+
+    int index = 0;
+
+    while (index < numBytes)
+    {
+
+        // decode tnf - first byte is tnf with bit flags
+        // see the NFDEF spec for more info
+        byte tnf_byte = data[index];
+        // bool mb = tnf_byte & 0x80;
+        bool me = tnf_byte & 0x40;
+        // bool cf = tnf_byte & 0x20;
+        bool sr = tnf_byte & 0x10;
+        bool il = tnf_byte & 0x8;
+        NdefRecord::TNF tnf = static_cast<NdefRecord::TNF>(tnf_byte & 0x7);
+
+        NdefRecord *record = new NdefRecord();
+        record->setTnf(tnf);
+
+        index++;
+        int typeLength = data[index];
+
+        uint32_t payloadLength = 0;
+        if (sr)
+        {
+            index++;
+            payloadLength = data[index];
+        }
+        else
+        {
+            payloadLength =
+                  (static_cast<uint32_t>(data[index])   << 24)
+                | (static_cast<uint32_t>(data[index+1]) << 16)
+                | (static_cast<uint32_t>(data[index+2]) << 8)
+                |  static_cast<uint32_t>(data[index+3]);
+            index += 4;
+        }
+
+        int idLength = 0;
+        if (il)
+        {
+            index++;
+            idLength = data[index];
+        }
+
+        index++;
+        record->setType(&data[index], typeLength);
+        index += typeLength;
+
+        if (il)
+        {
+            record->setId(&data[index], idLength);
+            index += idLength;
+        }
+
+        record->setPayload(&data[index], payloadLength);
+        index += payloadLength;
+
+        _records[_recordCount] = record;
+        _recordCount++;
+
+        if (me) break; // last message
+    }
+
+}
+
+NdefMessage::NdefMessage(const NdefMessage& rhs)
+{
+    _recordCount = 0;
+    for (unsigned int i = 0; i < rhs._recordCount; i++)
+    {
+        addRecord(*(rhs._records[i]));
+    }
+}
+
+NdefMessage::~NdefMessage()
+{
+    for (int i = 0; i < _recordCount; i++)
+    {
+        delete(_records[i]);
+    }
+}
+
+NdefMessage& NdefMessage::operator=(const NdefMessage& rhs)
+{
+
+    if (this != &rhs)
+    {
+
+        // delete existing records
+        for (uint8_t i = 0; i < _recordCount; i++)
+        {
+            delete(_records[i]);
+            _records[i] = (NdefRecord*)NULL;
+        }
+
+        _recordCount = 0;
+        for (unsigned int i = 0; i < _recordCount; i++)
+        {
+            addRecord(*(rhs._records[i]));
+        }
+    }
+    return *this;
+}
+
+uint8_t NdefMessage::getRecordCount()
+{
+    return _recordCount;
+}
+
+unsigned int NdefMessage::getEncodedSize()
+{
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < _recordCount; i++)
+    {
+        size += _records[i]->getEncodedSize();
+    }
+    return size;
+}
+
+// TODO change this to return uint8_t*
+void NdefMessage::encode(uint8_t* data)
+{
+    // assert sizeof(data) >= getEncodedSize()
+    uint8_t* data_ptr = &data[0];
+
+    for (unsigned int i = 0; i < _recordCount; i++)
+    {
+        _records[i]->encode(data_ptr, i == 0, (i + 1) == _recordCount);
+        // TODO can NdefRecord.encode return the record size?
+        data_ptr += _records[i]->getEncodedSize();
+    }
+
+}
+
+bool NdefMessage::addRecord(NdefRecord &record)
+{
+
+    if (_recordCount < MAX_NDEF_RECORDS)
+    {
+        _records[_recordCount] = new NdefRecord(record);
+        _recordCount++;
+        return true;
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.println(F("WARNING: Too many records. Increase MAX_NDEF_RECORDS."));
+#endif
+        return false;
+    }
+}
+
+void NdefMessage::addMimeMediaRecord(const char *mimeType, const char *payload)
+{
+    addMimeMediaRecord(mimeType, (uint8_t *)payload, strlen(payload)+1);
+}
+
+void NdefMessage::addMimeMediaRecord(const char *mimeType, byte* payload, const uint16_t payloadLength)
+{
+    NdefRecord r;
+    r.setTnf(NdefRecord::TNF_MIME_MEDIA);
+    r.setType((byte *)mimeType, strlen(mimeType)+1);
+    r.setPayload(payload, payloadLength);
+
+    addRecord(r);
+}
+
+void NdefMessage::addTextRecord(const char *text)
+{
+    addTextRecord(text, "en");
+}
+
+// Limited to language codes <= 5 chars (which is enough for "en" or "en-US")
+// Only supports UTF-8 encoding
+void NdefMessage::addTextRecord(const char *text, const char *language)
+{
+    NdefRecord r;
+
+    r.setTnf(NdefRecord::TNF_WELL_KNOWN);
+
+    uint8_t RTD_TEXT[] = { NdefRecord::RTD_TEXT };
+    r.setType(RTD_TEXT, sizeof(RTD_TEXT));
+
+    size_t languageLength = strlen(language);
+    languageLength = (languageLength > 5 ? 5 : languageLength);
+
+    byte header[6];
+    // This is the status byte, we always assume UTF-8 encoding here
+    header[0] = languageLength;
+    memcpy(header+1, language, languageLength);
+
+    r.setPayload(header, languageLength+1, (byte *)text, strlen(text));
+
+    addRecord(r);
+}
+
+void NdefMessage::addUriRecord(const char *uri)
+{
+    NdefRecord r;
+    r.setTnf(NdefRecord::TNF_WELL_KNOWN);
+
+    uint8_t RTD_URI[] = { NdefRecord::RTD_URI };
+    r.setType(RTD_URI, sizeof(RTD_URI));
+
+    size_t uriLength = strlen(uri);
+
+    byte header[] = {0x00};
+
+    r.setPayload(header, sizeof(header), (byte *)uri, uriLength);
+
+    addRecord(r);
+}
+
+// Type shoulde be something like my.com:xx
+void NdefMessage::addExternalRecord(const char *type, const byte *payload, const uint16_t payloadLength)
+{
+	NdefRecord r;
+	r.setTnf(NdefRecord::TNF_EXTERNAL_TYPE);
+
+	r.setType((byte *)type, strlen(type));
+    r.setPayload(payload, payloadLength);
+	addRecord(r);
+}
+
+void NdefMessage::addEmptyRecord()
+{
+    NdefRecord r;
+    r.setTnf(NdefRecord::TNF_EMPTY);
+    addRecord(r);
+}
+
+NdefRecord NdefMessage::getRecord(uint8_t index)
+{
+    if (index < _recordCount)
+    {
+        return *(_records[index]);
+    }
+    else
+    {
+        return NdefRecord(); // would rather return NULL
+    }
+}
+
+NdefRecord NdefMessage::operator[](uint8_t index)
+{
+    return getRecord(index);
+}
+
+#ifdef NDEF_USE_SERIAL
+void NdefMessage::print()
+{
+    Serial.print(F("\nNDEF Message "));Serial.print(_recordCount);Serial.print(F(" record"));
+    _recordCount == 1 ? Serial.print(", ") : Serial.print("s, ");
+    Serial.print(getEncodedSize());Serial.println(F(" bytes"));
+
+    for (unsigned int i = 0; i < _recordCount; i++)
+    {
+         _records[i]->print();
+    }
+}
+#endif

+ 42 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NdefMessage.h

@@ -0,0 +1,42 @@
+#ifndef NdefMessage_h
+#define NdefMessage_h
+
+#include <Ndef.h>
+#include <NdefRecord.h>
+
+#define MAX_NDEF_RECORDS 4
+
+class NdefMessage
+{
+    public:
+        NdefMessage(void);
+        NdefMessage(const byte *data, const uint16_t numBytes);
+        NdefMessage(const NdefMessage& rhs);
+        ~NdefMessage();
+        NdefMessage& operator=(const NdefMessage& rhs);
+
+        unsigned int getEncodedSize(); // need so we can pass array to encode
+        void encode(byte *data);
+
+        boolean addRecord(NdefRecord& record);
+        void addMimeMediaRecord(const char *mimeType, const char *payload);
+        void addMimeMediaRecord(const char *mimeType, byte *payload, const uint16_t payloadLength);
+        void addTextRecord(const char *text);
+        void addTextRecord(const char *text, const char *encoding);
+        void addUriRecord(const char *uri);
+        void addExternalRecord(const char *type, const byte *payload, const uint16_t payloadLength);
+        void addEmptyRecord();
+
+        uint8_t getRecordCount();
+        NdefRecord getRecord(uint8_t index);
+        NdefRecord operator[](uint8_t index);
+
+#ifdef NDEF_USE_SERIAL
+        void print();
+#endif
+    private:
+        NdefRecord *_records[MAX_NDEF_RECORDS];
+        uint8_t _recordCount;
+};
+
+#endif

+ 328 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NdefRecord.cpp

@@ -0,0 +1,328 @@
+#include "NdefRecord.h"
+
+NdefRecord::NdefRecord()
+{
+    _tnf = NdefRecord::TNF_EMPTY;
+    _typeLength = 0;
+    _payloadLength = 0;
+    _idLength = 0;
+    _type = NULL;
+    _payload = NULL;
+    _id = NULL;
+}
+
+NdefRecord::NdefRecord(const NdefRecord& rhs)
+{
+    _tnf = rhs._tnf;
+    _typeLength = rhs._typeLength;
+    _payloadLength = rhs._payloadLength;
+    _idLength = rhs._idLength;
+    _type = NULL;
+    _payload = NULL;
+    _id = NULL;
+
+    if (_typeLength)
+    {
+        _type = (byte*)malloc(_typeLength);
+        memcpy(_type, rhs._type, _typeLength);
+    }
+
+    if (_payloadLength)
+    {
+        _payload = (byte*)malloc(_payloadLength);
+        memcpy(_payload, rhs._payload, _payloadLength);
+    }
+
+    if (_idLength)
+    {
+        _id = (byte*)malloc(_idLength);
+        memcpy(_id, rhs._id, _idLength);
+    }
+
+}
+
+NdefRecord::~NdefRecord()
+{
+    free(_type);
+    free(_payload);
+    free(_id);
+}
+
+NdefRecord& NdefRecord::operator=(const NdefRecord& rhs)
+{
+    //Serial.println("NdefRecord ASSIGN");
+
+    if (this != &rhs)
+    {
+        // free existing
+        free(_type);
+        free(_payload);
+        free(_id);
+
+        _tnf = rhs._tnf;
+        _typeLength = rhs._typeLength;
+        _payloadLength = rhs._payloadLength;
+        _idLength = rhs._idLength;
+
+        if (_typeLength)
+        {
+            _type = (byte*)malloc(_typeLength);
+            if(_type)
+                memcpy(_type, rhs._type, _typeLength);
+            else
+                Serial.println("No type malloc");
+        }
+        else
+        {
+            _type = NULL;
+        }
+
+        if (_payloadLength)
+        {
+            _payload = (byte*)malloc(_payloadLength);
+            if(_payload)
+                memcpy(_payload, rhs._payload, _payloadLength);
+            else
+                Serial.println("No type malloc");
+        }
+        else
+        {
+            _payload = NULL;
+        }
+
+        if (_idLength)
+        {
+            _id = (byte*)malloc(_idLength);
+            if(_id)
+                memcpy(_id, rhs._id, _idLength);
+            else
+                Serial.println("No type malloc");
+        }
+        else
+        {
+            _id = NULL;
+        }
+    }
+    return *this;
+}
+
+// size of records in bytes
+unsigned int NdefRecord::getEncodedSize()
+{
+    unsigned int size = 2; // tnf + typeLength
+    if (_payloadLength > 0xFF)
+    {
+        size += 4;
+    }
+    else
+    {
+        size += 1;
+    }
+
+    if (_idLength)
+    {
+        size += 1;
+    }
+
+    size += (_typeLength + _payloadLength + _idLength);
+
+    return size;
+}
+
+void NdefRecord::encode(byte *data, bool firstRecord, bool lastRecord)
+{
+    // assert data > getEncodedSize()
+
+    uint8_t* data_ptr = &data[0];
+
+    *data_ptr = _getTnfByte(firstRecord, lastRecord);
+    data_ptr += 1;
+
+    *data_ptr = _typeLength;
+    data_ptr += 1;
+
+    if (_payloadLength <= 0xFF) {  // short record
+        *data_ptr = _payloadLength;
+        data_ptr += 1;
+    } else { // long format
+        // 4 bytes but we store length as an int
+        data_ptr[0] = 0x0; // (_payloadLength >> 24) & 0xFF;
+        data_ptr[1] = 0x0; // (_payloadLength >> 16) & 0xFF;
+        data_ptr[2] = (_payloadLength >> 8) & 0xFF;
+        data_ptr[3] = _payloadLength & 0xFF;
+        data_ptr += 4;
+    }
+
+    if (_idLength)
+    {
+        *data_ptr = _idLength;
+        data_ptr += 1;
+    }
+
+    //Serial.println(2);
+    memcpy(data_ptr, _type, _typeLength);
+    data_ptr += _typeLength;
+
+    if (_idLength)
+    {
+        memcpy(data_ptr, _id, _idLength);
+        data_ptr += _idLength;
+    }
+    
+    memcpy(data_ptr, _payload, _payloadLength);
+    data_ptr += _payloadLength;
+}
+
+byte NdefRecord::_getTnfByte(bool firstRecord, bool lastRecord)
+{
+    int value = _tnf;
+
+    if (firstRecord) { // mb
+        value = value | 0x80;
+    }
+
+    if (lastRecord) { //
+        value = value | 0x40;
+    }
+
+    // chunked flag is always false for now
+    // if (cf) {
+    //     value = value | 0x20;
+    // }
+
+    if (_payloadLength <= 0xFF) {
+        value = value | 0x10;
+    }
+
+    if (_idLength) {
+        value = value | 0x8;
+    }
+
+    return value;
+}
+
+NdefRecord::TNF NdefRecord::getTnf()
+{
+    return _tnf;
+}
+
+void NdefRecord::setTnf(NdefRecord::TNF tnf)
+{
+    _tnf = tnf;
+}
+
+unsigned int NdefRecord::getTypeLength()
+{
+    return _typeLength;
+}
+
+unsigned int NdefRecord::getPayloadLength()
+{
+    return _payloadLength;
+}
+
+unsigned int NdefRecord::getIdLength()
+{
+    return _idLength;
+}
+
+const byte* NdefRecord::getType()
+{
+    return _type;
+}
+
+void NdefRecord::setType(const byte *type, const unsigned int numBytes)
+{
+    free(_type);
+
+    _type = (uint8_t*)malloc(numBytes);
+    memcpy(_type, type, numBytes);
+    _typeLength = numBytes;
+}
+
+const byte* NdefRecord::getPayload()
+{
+    return _payload;
+}
+
+void NdefRecord::setPayload(const byte *payload, const int numBytes)
+{
+    free(_payload);
+
+    _payload = (byte*)malloc(numBytes);
+    memcpy(_payload, payload, numBytes);
+    _payloadLength = numBytes;
+}
+
+void NdefRecord::setPayload(const byte *header, const int headerLength, const byte *payload, const int payloadLength)
+{
+    free(_payload);
+
+    _payload = (byte*)malloc(headerLength+payloadLength);
+    memcpy(_payload, header, headerLength);
+    memcpy(_payload+headerLength, payload, payloadLength);
+    _payloadLength = headerLength+payloadLength;
+}
+
+const byte* NdefRecord::getId()
+{
+    return _id;
+}
+
+void NdefRecord::setId(const byte *id, const unsigned int numBytes)
+{
+    free(_id);
+
+    _id = (byte*)malloc(numBytes);
+    memcpy(_id, id, numBytes);
+    _idLength = numBytes;
+}
+#ifdef NDEF_USE_SERIAL
+
+void NdefRecord::print()
+{
+    Serial.println(F("  NDEF Record"));
+    Serial.print(F("    TNF 0x"));Serial.print(_tnf, HEX);Serial.print(" ");
+    switch (_tnf) {
+    case TNF_EMPTY:
+        Serial.println(F("Empty"));
+        break;
+    case TNF_WELL_KNOWN:
+        Serial.println(F("Well Known"));
+        break;
+    case TNF_MIME_MEDIA:
+        Serial.println(F("Mime Media"));
+        break;
+    case TNF_ABSOLUTE_URI:
+        Serial.println(F("Absolute URI"));
+        break;
+    case TNF_EXTERNAL_TYPE:
+        Serial.println(F("External"));
+        break;
+    case TNF_UNKNOWN:
+        Serial.println(F("Unknown"));
+        break;
+    case TNF_UNCHANGED:
+        Serial.println(F("Unchanged"));
+        break;
+    case TNF_RESERVED:
+        Serial.println(F("Reserved"));
+        break;
+    }
+    Serial.print(F("    Type Length 0x"));Serial.print(_typeLength, HEX);Serial.print(" ");Serial.println(_typeLength);
+    Serial.print(F("    Payload Length 0x"));Serial.print(_payloadLength, HEX);;Serial.print(" ");Serial.println(_payloadLength);
+    if (_idLength)
+    {
+        Serial.print(F("    Id Length 0x"));Serial.println(_idLength, HEX);
+    }
+    Serial.print(F("    Type "));PrintHexChar(_type, _typeLength);
+    // TODO chunk large payloads so this is readable
+    Serial.print(F("    Payload "));PrintHexChar(_payload, _payloadLength);
+    if (_idLength)
+    {
+        Serial.print(F("    Id "));PrintHexChar(_id, _idLength);
+    }
+    Serial.print(F("    Record is "));Serial.print(getEncodedSize());Serial.println(" bytes");
+
+}
+#endif

+ 52 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NdefRecord.h

@@ -0,0 +1,52 @@
+#ifndef NdefRecord_h
+#define NdefRecord_h
+
+#include <Due.h>
+#include <Arduino.h>
+#include <Ndef.h>
+
+
+class NdefRecord
+{
+    public:
+        enum TNF {TNF_EMPTY, TNF_WELL_KNOWN, TNF_MIME_MEDIA, TNF_ABSOLUTE_URI, TNF_EXTERNAL_TYPE, TNF_UNKNOWN, TNF_UNCHANGED, TNF_RESERVED};
+        enum RTD {RTD_TEXT = 0x54, RTD_URI = 0x55};
+        NdefRecord();
+        NdefRecord(const NdefRecord& rhs);
+        ~NdefRecord();
+        NdefRecord& operator=(const NdefRecord& rhs);
+
+        unsigned int getEncodedSize();
+        void encode(byte *data, bool firstRecord, bool lastRecord);
+
+        unsigned int getTypeLength();
+        unsigned int getPayloadLength();
+        unsigned int getIdLength();
+
+        NdefRecord::TNF getTnf();
+
+        const byte* getType();
+        const byte* getPayload();
+        const byte* getId();
+
+        void setTnf(NdefRecord::TNF tnf);
+        void setType(const byte *type, const unsigned int numBytes);
+        void setPayload(const byte *payload, const int numBytes);
+        void setPayload(const byte *header, const int headerLength, const byte *payload, const int payloadLength);
+        void setId(const byte *id, const unsigned int numBytes);
+
+#ifdef NDEF_USE_SERIAL
+        void print();
+#endif
+    private:
+        byte _getTnfByte(bool firstRecord, bool lastRecord);
+        TNF _tnf; // 3 bit
+        unsigned int _typeLength;
+        unsigned int _payloadLength;
+        unsigned int _idLength;
+        byte *_type;
+        byte *_payload;
+        byte *_id;
+};
+
+#endif

+ 203 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NfcAdapter.cpp

@@ -0,0 +1,203 @@
+#include <NfcAdapter.h>
+
+NfcAdapter::NfcAdapter(MFRC522 *interface)
+{
+    shield = interface;
+}
+
+NfcAdapter::~NfcAdapter(void)
+{
+}
+
+void NfcAdapter::begin(bool verbose)
+{
+#ifdef NDEF_USE_SERIAL
+    if (verbose)
+    {
+        shield->PCD_DumpVersionToSerial();
+    }
+#endif
+}
+
+bool NfcAdapter::tagPresent()
+{
+    // If tag has already been authenticated nothing else will work until we stop crypto (shouldn't hurt)
+    shield->PCD_StopCrypto1();
+
+    if(!(shield->PICC_IsNewCardPresent() && shield->PICC_ReadCardSerial()))
+    {
+        return false;
+    }
+
+    MFRC522::PICC_Type piccType = shield->PICC_GetType(shield->uid.sak);
+    return ((piccType == MFRC522::PICC_TYPE_MIFARE_1K) || (piccType == MFRC522::PICC_TYPE_MIFARE_UL));
+}
+
+bool NfcAdapter::erase()
+{
+    NdefMessage message = NdefMessage();
+    message.addEmptyRecord();
+    return write(message);
+}
+
+bool NfcAdapter::format()
+{
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+    if(shield->PICC_GetType(shield->uid.sak) == MFRC522::PICC_TYPE_MIFARE_1K)
+    {
+        MifareClassic mifareClassic = MifareClassic(shield);
+        return mifareClassic.formatNDEF();
+    }
+    else
+#endif
+    if(shield->PICC_GetType(shield->uid.sak) == MFRC522::PICC_TYPE_MIFARE_UL)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("No need for formating a UL"));
+#endif
+        return true;
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("Unsupported Tag."));
+#endif
+        return false;
+    }
+}
+
+bool NfcAdapter::clean()
+{
+    NfcTag::TagType type = guessTagType();
+
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+    if (type == NfcTag::TYPE_MIFARE_CLASSIC)
+    {
+        #ifdef NDEF_DEBUG
+        Serial.println(F("Cleaning Mifare Classic"));
+        #endif
+        MifareClassic mifareClassic = MifareClassic(shield);
+        return mifareClassic.formatMifare();
+    }
+    else
+#endif
+    if (type == NfcTag::TYPE_2)
+    {
+        #ifdef NDEF_DEBUG
+        Serial.println(F("Cleaning Mifare Ultralight"));
+        #endif
+        MifareUltralight ultralight = MifareUltralight(shield);
+        return ultralight.clean();
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("No driver for card type "));Serial.println(type);
+#endif
+        return false;
+    }
+
+}
+
+NfcTag NfcAdapter::read()
+{
+    uint8_t type = guessTagType();
+
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+    if (type == NfcTag::TYPE_MIFARE_CLASSIC)
+    {
+        #ifdef NDEF_DEBUG
+        Serial.println(F("Reading Mifare Classic"));
+        #endif
+        MifareClassic mifareClassic = MifareClassic(shield);
+        return mifareClassic.read();
+    }
+    else
+#endif
+    if (type == NfcTag::TYPE_2)
+    {
+        #ifdef NDEF_DEBUG
+        Serial.println(F("Reading Mifare Ultralight"));
+        #endif
+        MifareUltralight ultralight = MifareUltralight(shield);
+        return ultralight.read();
+    }
+    else if (type == NfcTag::TYPE_UNKNOWN)
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("Can not determine tag type"));
+#endif
+        return NfcTag(shield->uid.uidByte, shield->uid.size, NfcTag::TYPE_UNKNOWN);
+    }
+    else
+    {
+        // Serial.print(F("No driver for card type "));Serial.println(type);
+        // TODO should set type here
+        return NfcTag(shield->uid.uidByte, shield->uid.size, NfcTag::TYPE_UNKNOWN);
+    }
+
+}
+
+bool NfcAdapter::write(NdefMessage& ndefMessage)
+{
+    uint8_t type = guessTagType();
+
+#ifdef NDEF_SUPPORT_MIFARE_CLASSIC
+    if (type == NfcTag::TYPE_MIFARE_CLASSIC)
+    {
+
+        Serial.println(F("Writing Mifare Classic"));
+
+        MifareClassic mifareClassic = MifareClassic(shield);
+        return mifareClassic.write(ndefMessage);
+    }
+    else
+#endif
+    if (type == NfcTag::TYPE_2)
+    {
+
+        Serial.println(F("Writing Mifare Ultralight"));
+
+        MifareUltralight mifareUltralight = MifareUltralight(shield);
+        return mifareUltralight.write(ndefMessage);
+    }
+    else if (type == NfcTag::TYPE_UNKNOWN)
+    {
+
+        Serial.print(F("Can not determine tag type"));
+
+        return false;
+    }
+    else
+    {
+#ifdef NDEF_USE_SERIAL
+        Serial.print(F("No driver for card type "));Serial.println(type);
+#endif
+        return false;
+    }
+}
+
+// Current tag will not be "visible" until removed from the RFID field
+void NfcAdapter::haltTag() {
+    shield->PICC_HaltA();
+    shield->PCD_StopCrypto1();
+}
+
+NfcTag::TagType NfcAdapter::guessTagType()
+{
+
+    MFRC522::PICC_Type piccType = shield->PICC_GetType(shield->uid.sak);
+
+    if (piccType == MFRC522::PICC_TYPE_MIFARE_1K)
+    {
+        return NfcTag::TYPE_MIFARE_CLASSIC;
+    } 
+    else if (piccType == MFRC522::PICC_TYPE_MIFARE_UL)
+    {
+        return NfcTag::TYPE_2;
+    }
+    else
+    {
+        return NfcTag::TYPE_UNKNOWN;
+    }
+}

+ 35 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NfcAdapter.h

@@ -0,0 +1,35 @@
+#ifndef NfcAdapter_h
+#define NfcAdapter_h
+
+#include <MFRC522.h>
+#include <NfcTag.h>
+#include <Ndef.h>
+
+// Drivers
+#include <MifareClassic.h>
+#include <MifareUltralight.h>
+
+//#define NDEF_DEBUG 1
+
+class NfcAdapter {
+    public:
+        NfcAdapter(MFRC522 *interface);
+
+        ~NfcAdapter(void);
+        void begin(bool verbose=true);
+        bool tagPresent(); // tagAvailable
+        NfcTag read();
+        bool write(NdefMessage& ndefMessage);
+        // erase tag by writing an empty NDEF record
+        bool erase();
+        // format a tag as NDEF
+        bool format();
+        // reset tag back to factory state
+        bool clean();
+        void haltTag();
+    private:
+        MFRC522* shield;
+        NfcTag::TagType guessTagType();
+};
+
+#endif

+ 123 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NfcTag.cpp

@@ -0,0 +1,123 @@
+#include <NfcTag.h>
+
+NfcTag::NfcTag(byte *uid, uint8_t  uidLength, TagType tagType)
+{
+    _uid = uid;
+    _uidLength = uidLength;
+    _tagType = tagType;
+    _ndefMessage = (NdefMessage*)NULL;
+    _isFormatted = false;
+}
+
+NfcTag::NfcTag(byte *uid, uint8_t  uidLength, TagType tagType, bool isFormatted)
+{
+    _uid = uid;
+    _uidLength = uidLength;
+    _tagType = tagType;
+    _ndefMessage = (NdefMessage*)NULL;
+    _isFormatted = isFormatted;
+}
+
+NfcTag::NfcTag(byte *uid, uint8_t  uidLength, TagType tagType, NdefMessage& ndefMessage)
+{
+    _uid = uid;
+    _uidLength = uidLength;
+    _tagType = tagType;
+    _ndefMessage = new NdefMessage(ndefMessage);
+    _isFormatted = true; // If it has a message it's formatted
+}
+
+NfcTag::NfcTag(byte *uid, uint8_t uidLength, TagType tagType, const byte *ndefData, const uint16_t ndefDataLength)
+{
+    _uid = uid;
+    _uidLength = uidLength;
+    _tagType = tagType;
+    _ndefMessage = new NdefMessage(ndefData, ndefDataLength);
+    _isFormatted = true; // If it has a message it's formatted
+}
+
+NfcTag::~NfcTag()
+{
+    delete _ndefMessage;
+}
+
+NfcTag& NfcTag::operator=(const NfcTag& rhs)
+{
+    if (this != &rhs)
+    {
+        delete _ndefMessage;
+        _uid = rhs._uid;
+        _uidLength = rhs._uidLength;
+        _tagType = rhs._tagType;
+        _ndefMessage = new NdefMessage(*rhs._ndefMessage);
+    }
+    return *this;
+}
+
+uint8_t NfcTag::getUidLength()
+{
+    return _uidLength;
+}
+
+void NfcTag::getUid(byte *uid, uint8_t *uidLength)
+{
+    memcpy(uid, _uid, _uidLength < *uidLength ? _uidLength : *uidLength);
+    *uidLength = _uidLength;
+}
+
+String NfcTag::getUidString()
+{
+    String uidString = "";
+    for (unsigned int i = 0; i < _uidLength; i++)
+    {
+        if (i > 0)
+        {
+            uidString += " ";
+        }
+
+        if (_uid[i] < 0xF)
+        {
+            uidString += "0";
+        }
+
+        uidString += String((unsigned int)_uid[i], (unsigned char)HEX);
+    }
+    uidString.toUpperCase();
+    return uidString;
+}
+
+NfcTag::TagType NfcTag::getTagType()
+{
+    return _tagType;
+}
+
+boolean NfcTag::hasNdefMessage()
+{
+    return (_ndefMessage != NULL);
+}
+
+NdefMessage NfcTag::getNdefMessage()
+{
+    return *_ndefMessage;
+}
+
+bool NfcTag::isFormatted()
+{
+    return _isFormatted;
+}
+#ifdef NDEF_USE_SERIAL
+
+void NfcTag::print()
+{
+    Serial.print(F("NFC Tag - "));Serial.println(_tagType);
+    Serial.print(F("UID "));Serial.println(getUidString());
+    if (_ndefMessage == NULL)
+    {
+        Serial.println(F("\nNo NDEF Message"));
+    }
+    else
+    {
+        _ndefMessage->print();
+    }
+}
+#endif

+ 41 - 0
arduinoLibrary/rc522/NDEF_MFRC522/src/NfcTag.h

@@ -0,0 +1,41 @@
+#ifndef NfcTag_h
+#define NfcTag_h
+
+#include <inttypes.h>
+#include <Arduino.h>
+#include <NdefMessage.h>
+
+class NfcTag
+{
+    public:
+        enum TagType { TYPE_MIFARE_CLASSIC = 0, TYPE_1, TYPE_2, TYPE_3, TYPE_4, TYPE_UNKNOWN = 99 };
+        NfcTag(byte *uid, uint8_t uidLength, TagType tagType);
+        NfcTag(byte *uid, uint8_t uidLength, TagType tagType, bool isFormatted);
+        NfcTag(byte *uid, uint8_t uidLength, TagType tagType, NdefMessage& ndefMessage);
+        NfcTag(byte *uid, uint8_t uidLength, TagType tagType, const byte *ndefData, const uint16_t ndefDataLength);
+        ~NfcTag(void);
+        NfcTag& operator=(const NfcTag &rhs);
+        uint8_t getUidLength();
+        void getUid(byte *uid, uint8_t *uidLength);
+        String getUidString();
+        TagType getTagType();
+        bool hasNdefMessage();
+        NdefMessage getNdefMessage();
+        bool isFormatted();
+#ifdef NDEF_USE_SERIAL
+        void print();
+#endif
+    private:
+        byte *_uid;
+        uint8_t _uidLength;
+        TagType _tagType; // Mifare Classic, NFC Forum Type {1,2,3,4}, Unknown
+        NdefMessage *_ndefMessage;
+        /**
+         * if tag is not formatted it is most probably in HALTED state as soon as we realize that
+         * because authentication failed => We need to call PICC_WakeupA
+         */
+        bool _isFormatted; 
+        // TODO capacity
+};
+
+#endif

+ 6 - 3
bledome/bledome.ino

@@ -1,5 +1,6 @@
 #include "blemanager.h"
-#include "rfid.h"
+// #include "rfid.h"
+#include "ndef.h"
 #include "qr.h"
 
  void setup() {
@@ -7,7 +8,8 @@
   Serial.begin(19200);
   
   bleSetup();
-  rfidSetup();
+  // rfidSetup();
+  ndefSetup();
   qrSetup();
 
   Serial.println("lllalalal");
@@ -17,7 +19,8 @@
  void loop(){
 
   bleLoop();
-  rfidLoop();
+  // rfidSetup();
+  ndefLoop();
   qrLoop();
 
  }

+ 127 - 0
bledome/ndef.h

@@ -0,0 +1,127 @@
+#include <SPI.h>
+#include <MFRC522.h>
+#include "NfcAdapter.h"
+
+// 定义RC522模块的引脚
+#define SS_PIN    7 // SDA
+#define RST_PIN   3 // RST
+
+String errorValue = "r:rfid error";
+String notRfid = "r:not rfid";
+String writeValue = "r:write ok";
+
+// 创建MFRC522对象
+MFRC522 mfrc522(SS_PIN, RST_PIN);
+
+NfcAdapter nfc = NfcAdapter(&mfrc522);
+
+void ndefSetup(void) {
+
+    SPI.begin();        // Init SPI bus
+    mfrc522.PCD_Init(); // Init MFRC522
+    nfc.begin();
+}
+
+void readRFID(){
+
+  String str = errorValue;
+
+  if(nfc.tagPresent()){
+        Serial.println("Reading NFC tag");
+        NfcTag tag = nfc.read();
+        Serial.println(tag.getTagType());
+        Serial.print("UID: ");Serial.println(tag.getUidString());
+        NdefMessage message = tag.getNdefMessage();
+        Serial.print("\nThis NFC Tag contains an NDEF Message with ");
+        Serial.print(message.getRecordCount());
+        Serial.print(" NDEF Record");
+
+        int recordCount = message.getRecordCount();
+        for (int i = 0; i < recordCount; i++){
+
+          Serial.print("\nNDEF Record ");Serial.println(i+1);
+          NdefRecord record = message.getRecord(i);
+          Serial.print("  TNF: ");Serial.println(record.getTnf());
+          String type((char*)record.getType());
+          Serial.println("  Type: " + type);
+
+          int payloadLength = record.getPayloadLength();
+          const byte *payload = record.getPayload();
+
+          String payloadHEX((char*)payload);
+          Serial.println("  Payload (HEX): " + payloadHEX);
+
+          String payloadAsString = "";
+          for (int c = 0; c < payloadLength; c++) {
+              payloadAsString += (char)payload[c];
+          }
+
+          Serial.print("  Payload (as String): ");
+          Serial.println(payloadAsString);
+
+          if (record.getIdLength() > 0) {
+              String ID((char*)record.getId());
+              Serial.println("  ID: " + ID);
+          }
+
+          str = payloadAsString;
+
+        }
+
+  }
+
+  pCharacteristic->setValue(str.c_str());
+
+}
+
+void writeRFID(String data){
+
+  String str = errorValue;
+
+  if(nfc.tagPresent()){
+
+    Serial.println("Writing multiple records to NFC tag");
+    NdefMessage message = NdefMessage();
+    message.addTextRecord(data.c_str());
+    // message.addUriRecord("https://arduino.cc");
+    boolean success = nfc.write(message);
+    if (success)str = writeValue;
+  }
+
+  
+  pCharacteristic->setValue(str.c_str());
+}
+
+//0:开头字符串读取 1:开头字符串写入
+void ndefCommand(){
+
+    String command = pCharacteristic->getValue().c_str();
+
+    if (command.startsWith("0:")) {
+
+      readRFID();
+
+    } else if (command.startsWith("1:")) {
+
+      String data = command.substring(2);
+      writeRFID(data);
+      
+    }
+}
+
+int loopNdefSize=1000; //loop间隔
+int ndefMillisTime;
+void ndefLoop(void) {
+
+    //1秒读取一次指令
+  int ndefTimeCurrent = millis();
+  
+  if(ndefTimeCurrent<=0)ndefMillisTime = ndefTimeCurrent;
+
+  if((ndefTimeCurrent - ndefMillisTime)>loopNdefSize){
+
+    ndefMillisTime = ndefTimeCurrent;
+    ndefCommand();
+  }
+
+}

二進制
扫码枪文档.doc