MFRC522 example project for FRDM

Dependencies:   MFRC522 mbed

Files at this revision

API Documentation at this revision

Comitter:
AtomX
Date:
Wed Dec 18 00:46:40 2013 +0000
Parent:
0:1d9c7c0b5015
Commit message:
created MFRC522 lib

Changed in this revision

MFRC522.cpp Show diff for this revision Revisions of this file
MFRC522.h Show diff for this revision Revisions of this file
MFRC522.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 1d9c7c0b5015 -r 8e41a7b03f45 MFRC522.cpp
--- a/MFRC522.cpp	Sat Dec 14 21:41:08 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1189 +0,0 @@
-/*
-* MFRC522.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
-* _Please_ see the comments in MFRC522.h - they give useful hints and background.
-* Released into the public domain.
-*/
-
-#include "MFRC522.h"
-
-
-#define MFRC522_MaxPICCs       9
-#define MFRC522_MaxError       10
-
-static std::string _TypeNamePICC[MFRC522_MaxPICCs] =
-{
-  "Unknown type",
-  "PICC compliant with ISO/IEC 14443-4",
-  "PICC compliant with ISO/IEC 18092 (NFC)",
-  "MIFARE Mini, 320 bytes",
-  "MIFARE 1KB",
-  "MIFARE 4KB",
-  "MIFARE Ultralight or Ultralight C",
-  "MIFARE Plus",
-  "MIFARE TNP3XXX"
-};
-
-static std::string _ErrorMessage[MFRC522_MaxError] =
-{
-  "Unknown error",
-  "Success",
-  "Error in communication",
-  "Collision detected",
-  "Timeout in communication",
-  "A buffer is not big enough",
-  "Internal error in the code, should not happen",
-  "Invalid argument",
-  "The CRC_A does not match",
-  "A MIFARE PICC responded with NAK"
-};
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for setting up the driver
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Constructor.
- * Prepares the output pins.
- */
-MFRC522::MFRC522(PinName mosi,
-                 PinName miso,
-                 PinName sclk,
-                 PinName cs,
-                 PinName reset) : m_SPI(mosi, miso, sclk), m_CS(cs), m_RESET(reset)
-{
-  /* init MFRC522 SPI BUS */
-  m_SPI.format(8, 0);
-  m_SPI.frequency(8000000);
-
-  /* init MFRC522 SPI_CS pin */
-  m_CS       = 1;
-
-  /* init MFRC522 RESET pin */
-  m_RESET    = 1;
-} // End constructor
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Basic interface functions for communicating with the MFRC522
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Writes a byte to the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_WriteRegister(uint8_t reg, uint8_t value)
-{
-  m_CS = 0; /* Select SPI Chip MFRC522 */
-
-  // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
-  (void) m_SPI.write(reg & 0x7E);
-  (void) m_SPI.write(value);
-
-  m_CS = 1; /* Release SPI Chip MFRC522 */
-} // End PCD_WriteRegister()
-
-/**
- * Writes a number of bytes to the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_WriteRegister(uint8_t reg, uint8_t count, uint8_t *values)
-{
-  m_CS = 0; /* Select SPI Chip MFRC522 */
-
-  // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
-  (void) m_SPI.write(reg & 0x7E);
-  for (uint8_t index = 0; index < count; index++)
-  {
-    (void) m_SPI.write(values[index]);
-  }
-
-  m_CS = 1; /* Release SPI Chip MFRC522 */
-} // End PCD_WriteRegister()
-
-/**
- * Reads a byte from the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-uint8_t MFRC522::PCD_ReadRegister(uint8_t reg)
-{
-  uint8_t value;
-  m_CS = 0; /* Select SPI Chip MFRC522 */
-
-  // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
-  (void) m_SPI.write(0x80 | reg);
-  value = m_SPI.write(0);          // Read the value back. Send 0 to stop reading.
-
-  m_CS = 1; /* Release SPI Chip MFRC522 */
-  return value;
-} // End PCD_ReadRegister()
-
-/**
- * Reads a number of bytes from the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_ReadRegister(uint8_t reg, uint8_t count, uint8_t *values, uint8_t rxAlign)
-{
-  if (count == 0) { return; }
-
-  //Serial.print("Reading ");   Serial.print(count); Serial.println(" bytes from register.");
-  uint8_t address = 0x80 | reg;  // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
-  uint8_t index = 0;             // Index in values array.
-
-  m_CS = 0;                      /* Select SPI Chip MFRC522 */
-  count--;                       // One read is performed outside of the loop
-  (void) m_SPI.write(address);   // Tell MFRC522 which address we want to read
-
-  while (index < count)
-  {
-    if ((index == 0) && rxAlign) // Only update bit positions rxAlign..7 in values[0]
-    {
-      // Create bit mask for bit positions rxAlign..7
-      uint8_t mask = 0;
-      for (uint8_t i = rxAlign; i <= 7; i++)
-      {
-        mask |= (1 << i);
-      }
-
-      // Read value and tell that we want to read the same address again.
-      uint8_t value = m_SPI.write(address);
-
-      // Apply mask to both current value of values[0] and the new data in value.
-      values[0] = (values[index] & ~mask) | (value & mask);
-    }
-    else
-    {
-      // Read value and tell that we want to read the same address again.
-      values[index] = m_SPI.write(address);
-    }
-
-    index++;
-  }
-
-  values[index] = m_SPI.write(0); // Read the final byte. Send 0 to stop reading.
-
-  m_CS = 1;                       /* Release SPI Chip MFRC522 */
-} // End PCD_ReadRegister()
-
-/**
- * Sets the bits given in mask in register reg.
- */
-void MFRC522::PCD_SetRegisterBitMask(uint8_t reg, uint8_t mask)
-{
-  uint8_t tmp;
-  tmp = PCD_ReadRegister(reg);
-  PCD_WriteRegister(reg, tmp | mask);     // set bit mask
-} // End PCD_SetRegisterBitMask()
-
-/**
- * Clears the bits given in mask from register reg.
- */
-void MFRC522::PCD_ClearRegisterBitMask(uint8_t reg, uint8_t mask)
-{
-  uint8_t tmp;
-  tmp = PCD_ReadRegister(reg);
-  PCD_WriteRegister(reg, tmp & (~mask));    // clear bit mask
-} // End PCD_ClearRegisterBitMask()
-
-
-/**
- * Use the CRC coprocessor in the MFRC522 to calculate a CRC_A.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PCD_CalculateCRC(uint8_t *data, uint8_t length, uint8_t *result)
-{
-  PCD_WriteRegister(CommandReg, PCD_Idle);      // Stop any active command.
-  PCD_WriteRegister(DivIrqReg, 0x04);         // Clear the CRCIRq interrupt request bit
-  PCD_SetRegisterBitMask(FIFOLevelReg, 0x80);   // FlushBuffer = 1, FIFO initialization
-  PCD_WriteRegister(FIFODataReg, length, data);   // Write data to the FIFO
-  PCD_WriteRegister(CommandReg, PCD_CalcCRC);   // Start the calculation
-
-  // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73�s.
-  uint16_t i = 5000;
-  uint8_t n;
-  while (1)
-  {
-    n = PCD_ReadRegister(DivIrqReg);  // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq   reserved CRCIRq reserved reserved
-    if (n & 0x04)
-    {
-      // CRCIRq bit set - calculation done
-      break;
-    }
-    if (--i == 0)
-    {
-      // The emergency break. We will eventually terminate on this one after 89ms.
-      // Communication with the MFRC522 might be down.
-      return STATUS_TIMEOUT;
-    }
-  }
-
-  // Stop calculating CRC for new content in the FIFO.
-  PCD_WriteRegister(CommandReg, PCD_Idle);
-
-  // Transfer the result from the registers to the result buffer
-  result[0] = PCD_ReadRegister(CRCResultRegL);
-  result[1] = PCD_ReadRegister(CRCResultRegH);
-  return STATUS_OK;
-} // End PCD_CalculateCRC()
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for manipulating the MFRC522
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes the MFRC522 chip.
- */
-void MFRC522::PCD_Init()
-{
-  /* Reset MFRC522 */
-  m_RESET = 0;
-  wait_ms(10);
-  m_RESET = 1;
-  // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74�s. Let us be generous: 50ms.
-  wait_ms(50);
-
-  // When communicating with a PICC we need a timeout if something goes wrong.
-  // f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
-  // TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
-  PCD_WriteRegister(TModeReg, 0x80);      // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
-  PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25�s.
-  PCD_WriteRegister(TReloadRegH, 0x03);   // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
-  PCD_WriteRegister(TReloadRegL, 0xE8);
-
-  PCD_WriteRegister(TxASKReg, 0x40);      // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
-  PCD_WriteRegister(ModeReg, 0x3D);       // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
-  PCD_AntennaOn();                        // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
-} // End PCD_Init()
-
-/**
- * Performs a soft reset on the MFRC522 chip and waits for it to be ready again.
- */
-void MFRC522::PCD_Reset()
-{
-  PCD_WriteRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
-  // The datasheet does not mention how long the SoftRest command takes to complete.
-  // But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
-  // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74�s. Let us be generous: 50ms.
-  wait_ms(50);
-
-  // Wait for the PowerDown bit in CommandReg to be cleared
-  while (PCD_ReadRegister(CommandReg) & (1<<4))
-  {
-    // PCD still restarting - unlikely after waiting 50ms, but better safe than sorry.
-  }
-} // End PCD_Reset()
-
-/**
- * Turns the antenna on by enabling pins TX1 and TX2.
- * After a reset these pins disabled.
- */
-void MFRC522::PCD_AntennaOn()
-{
-  uint8_t value = PCD_ReadRegister(TxControlReg);
-  if ((value & 0x03) != 0x03)
-  {
-    PCD_WriteRegister(TxControlReg, value | 0x03);
-  }
-} // End PCD_AntennaOn()
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for communicating with PICCs
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Executes the Transceive command.
- * CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PCD_TransceiveData(uint8_t *sendData,   ///< Pointer to the data to transfer to the FIFO.
-                                 uint8_t sendLen,   ///< Number of bytes to transfer to the FIFO.
-                                 uint8_t *backData,   ///< NULL or pointer to buffer if data should be read back after executing the command.
-                                 uint8_t *backLen,    ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
-                                 uint8_t *validBits,  ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default NULL.
-                                 uint8_t rxAlign,   ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
-                                 bool checkCRC)   ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
-{
-  uint8_t waitIRq = 0x30;    // RxIRq and IdleIRq
-  return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
-} // End PCD_TransceiveData()
-
-/**
- * Transfers data to the MFRC522 FIFO, executes a commend, waits for completion and transfers data back from the FIFO.
- * CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PCD_CommunicateWithPICC(uint8_t command,   ///< The command to execute. One of the PCD_Command enums.
-                                      uint8_t waitIRq,   ///< The bits in the ComIrqReg register that signals successful completion of the command.
-                                      uint8_t *sendData,   ///< Pointer to the data to transfer to the FIFO.
-                                      uint8_t sendLen,   ///< Number of bytes to transfer to the FIFO.
-                                      uint8_t *backData,   ///< NULL or pointer to buffer if data should be read back after executing the command.
-                                      uint8_t *backLen,    ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
-                                      uint8_t *validBits,  ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
-                                      uint8_t rxAlign,   ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
-                                      bool checkCRC)   ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
-{
-  uint8_t n, _validBits = 0;
-  uint32_t i;
-
-  // Prepare values for BitFramingReg
-  uint8_t txLastBits = validBits ? *validBits : 0;
-  uint8_t bitFraming = (rxAlign << 4) + txLastBits;   // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
-
-  PCD_WriteRegister(CommandReg, PCD_Idle);            // Stop any active command.
-  PCD_WriteRegister(ComIrqReg, 0x7F);                 // Clear all seven interrupt request bits
-  PCD_SetRegisterBitMask(FIFOLevelReg, 0x80);         // FlushBuffer = 1, FIFO initialization
-  PCD_WriteRegister(FIFODataReg, sendLen, sendData);  // Write sendData to the FIFO
-  PCD_WriteRegister(BitFramingReg, bitFraming);       // Bit adjustments
-  PCD_WriteRegister(CommandReg, command);             // Execute the command
-  if (command == PCD_Transceive)
-  {
-    PCD_SetRegisterBitMask(BitFramingReg, 0x80);      // StartSend=1, transmission of data starts
-  }
-
-  // Wait for the command to complete.
-  // In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
-  // Each iteration of the do-while-loop takes 17.86�s.
-  i = 2000;
-  while (1)
-  {
-    n = PCD_ReadRegister(ComIrqReg);  // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq   HiAlertIRq LoAlertIRq ErrIRq TimerIRq
-    if (n & waitIRq) 
-    {          // One of the interrupts that signal success has been set.
-      break;
-    }
-    
-    if (n & 0x01) 
-    {           // Timer interrupt - nothing received in 25ms
-      return STATUS_TIMEOUT;
-    }
-    
-    if (--i == 0) 
-    {           // The emergency break. If all other condions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
-      return STATUS_TIMEOUT;
-    }
-  }
-
-  // Stop now if any errors except collisions were detected.
-  uint8_t errorRegValue = PCD_ReadRegister(ErrorReg); // ErrorReg[7..0] bits are: WrErr TempErr reserved BufferOvfl   CollErr CRCErr ParityErr ProtocolErr
-  if (errorRegValue & 0x13) 
-  {  // BufferOvfl ParityErr ProtocolErr
-    return STATUS_ERROR;
-  }
-
-  // If the caller wants data back, get it from the MFRC522.
-  if (backData && backLen)
-  {
-    n = PCD_ReadRegister(FIFOLevelReg);           // Number of bytes in the FIFO
-    if (n > *backLen)
-    {
-      return STATUS_NO_ROOM;
-    }
-
-    *backLen = n;                       // Number of bytes returned
-    PCD_ReadRegister(FIFODataReg, n, backData, rxAlign);    // Get received data from FIFO
-    _validBits = PCD_ReadRegister(ControlReg) & 0x07; // RxLastBits[2:0] indicates the number of valid bits in the last received byte. If this value is 000b, the whole byte is valid.
-    if (validBits)
-    {
-      *validBits = _validBits;
-    }
-  }
-
-  // Tell about collisions
-  if (errorRegValue & 0x08) { // CollErr
-    return STATUS_COLLISION;
-  }
-
-  // Perform CRC_A validation if requested.
-  if (backData && backLen && checkCRC)
-  {
-    // In this case a MIFARE Classic NAK is not OK.
-    if (*backLen == 1 && _validBits == 4)
-    {
-      return STATUS_MIFARE_NACK;
-    }
-
-    // We need at least the CRC_A value and all 8 bits of the last byte must be received.
-    if (*backLen < 2 || _validBits != 0)
-    {
-      return STATUS_CRC_WRONG;
-    }
-
-    // Verify CRC_A - do our own calculation and store the control in controlBuffer.
-    uint8_t controlBuffer[2];
-    n = PCD_CalculateCRC(&backData[0], *backLen - 2, &controlBuffer[0]);
-    if (n != STATUS_OK)
-    {
-      return n;
-    }
-
-    if ((backData[*backLen - 2] != controlBuffer[0]) || (backData[*backLen - 1] != controlBuffer[1]))
-    {
-      return STATUS_CRC_WRONG;
-    }
-  }
-
-  return STATUS_OK;
-} // End PCD_CommunicateWithPICC()
-
-/**
- * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PICC_RequestA(uint8_t *bufferATQA, uint8_t *bufferSize)
-{
-  return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
-} // End PICC_RequestA()
-
-/**
- * Transmits a 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.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PICC_WakeupA(uint8_t *bufferATQA, uint8_t *bufferSize)
-{
-  return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
-} // End PICC_WakeupA()
-
-/**
- * Transmits REQA or WUPA commands.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PICC_REQA_or_WUPA(uint8_t command, uint8_t *bufferATQA, uint8_t *bufferSize)
-{
-  uint8_t validBits;
-  uint8_t status;
-
-  if (bufferATQA == NULL || *bufferSize < 2) {  // The ATQA response is 2 bytes long.
-    return STATUS_NO_ROOM;
-  }
-
-  PCD_ClearRegisterBitMask(CollReg, 0x80);      // ValuesAfterColl=1 => Bits received after collision are cleared.
-  validBits = 7;                    // For REQA and WUPA we need the short frame format - transmit only 7 bits of the last (and only) byte. TxLastBits = BitFramingReg[2..0]
-  status = PCD_TransceiveData(&command, 1, bufferATQA, bufferSize, &validBits);
-  if (status != STATUS_OK)
-  {
-    return status;
-  }
-
-  if (*bufferSize != 2 || validBits != 0) {   // ATQA must be exactly 16 bits.
-    return STATUS_ERROR;
-  }
-
-  return STATUS_OK;
-} // End PICC_REQA_or_WUPA()
-
-/**
- * Transmits SELECT/ANTICOLLISION commands to select a single PICC.
- * Before calling this function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or PICC_WakeupA().
- * On success:
- *    - The chosen PICC is in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)
- *    - The UID size and value of the chosen PICC is returned in *uid along with the SAK.
- *
- * A PICC UID consists of 4, 7 or 10 bytes.
- * Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two or three iterations are used:
- *    UID size  Number of UID bytes   Cascade levels    Example of PICC
- *    ========  ===================   ==============    ===============
- *    single         4            1       MIFARE Classic
- *    double         7            2       MIFARE Ultralight
- *    triple        10            3       Not currently in use?
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PICC_Select(Uid *uid, uint8_t validBits)
-{
-  bool uidComplete;
-  bool selectDone;
-  bool useCascadeTag;
-  uint8_t cascadeLevel = 1;
-  uint8_t result;
-  uint8_t count;
-  uint8_t index;
-  uint8_t uidIndex;          // The first index in uid->uidByte[] that is used in the current Cascade Level.
-  uint8_t currentLevelKnownBits;   // The number of known UID bits in the current Cascade Level.
-  uint8_t buffer[9];         // The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
-  uint8_t bufferUsed;        // The number of bytes used in the buffer, ie the number of bytes to transfer to the FIFO.
-  uint8_t rxAlign;         // Used in BitFramingReg. Defines the bit position for the first bit received.
-  uint8_t txLastBits;        // Used in BitFramingReg. The number of valid bits in the last transmitted byte.
-  uint8_t *responseBuffer;
-  uint8_t responseLength;
-
-  // Description of buffer structure:
-  //    Byte 0: SEL         Indicates the Cascade Level: PICC_CMD_SEL_CL1, PICC_CMD_SEL_CL2 or PICC_CMD_SEL_CL3
-  //    Byte 1: NVB         Number of Valid Bits (in complete command, not just the UID): High nibble: complete bytes, Low nibble: Extra bits.
-  //    Byte 2: UID-data or CT    See explanation below. CT means Cascade Tag.
-  //    Byte 3: UID-data
-  //    Byte 4: UID-data
-  //    Byte 5: UID-data
-  //    Byte 6: BCC         Block Check Character - XOR of bytes 2-5
-  //    Byte 7: CRC_A
-  //    Byte 8: CRC_A
-  // The BCC and CRC_A is only transmitted if we know all the UID bits of the current Cascade Level.
-  //
-  // Description of bytes 2-5: (Section 6.5.4 of the ISO/IEC 14443-3 draft: UID contents and cascade levels)
-  //    UID size  Cascade level Byte2 Byte3 Byte4 Byte5
-  //    ========  ============= ===== ===== ===== =====
-  //     4 bytes    1     uid0  uid1  uid2  uid3
-  //     7 bytes    1     CT    uid0  uid1  uid2
-  //                2     uid3  uid4  uid5  uid6
-  //    10 bytes    1     CT    uid0  uid1  uid2
-  //                2     CT    uid3  uid4  uid5
-  //                3     uid6  uid7  uid8  uid9
-
-  // Sanity checks
-  if (validBits > 80)
-  {
-    return STATUS_INVALID;
-  }
-
-  // Prepare MFRC522
-  PCD_ClearRegisterBitMask(CollReg, 0x80);      // ValuesAfterColl=1 => Bits received after collision are cleared.
-
-  // Repeat Cascade Level loop until we have a complete UID.
-  uidComplete = false;
-  while ( ! uidComplete)
-  {
-    // Set the Cascade Level in the SEL byte, find out if we need to use the Cascade Tag in byte 2.
-    switch (cascadeLevel)
-    {
-      case 1:
-        buffer[0] = PICC_CMD_SEL_CL1;
-        uidIndex = 0;
-        useCascadeTag = validBits && uid->size > 4; // When we know that the UID has more than 4 bytes
-        break;
-
-      case 2:
-        buffer[0] = PICC_CMD_SEL_CL2;
-        uidIndex = 3;
-        useCascadeTag = validBits && uid->size > 7; // When we know that the UID has more than 7 bytes
-        break;
-
-      case 3:
-        buffer[0] = PICC_CMD_SEL_CL3;
-        uidIndex = 6;
-        useCascadeTag = false;            // Never used in CL3.
-        break;
-
-      default:
-        return STATUS_INTERNAL_ERROR;
-        //break;
-    }
-
-    // How many UID bits are known in this Cascade Level?
-    if(validBits > (8 * uidIndex))
-    {
-      currentLevelKnownBits = validBits - (8 * uidIndex);
-    }
-    else
-    {
-      currentLevelKnownBits = 0;
-    }
-    // Copy the known bits from uid->uidByte[] to buffer[]
-    index = 2; // destination index in buffer[]
-    if (useCascadeTag)
-    {
-      buffer[index++] = PICC_CMD_CT;
-    }
-
-    uint8_t bytesToCopy = currentLevelKnownBits / 8 + (currentLevelKnownBits % 8 ? 1 : 0); // The number of bytes needed to represent the known bits for this level.
-    if (bytesToCopy)
-    {
-      uint8_t maxBytes = useCascadeTag ? 3 : 4; // Max 4 bytes in each Cascade Level. Only 3 left if we use the Cascade Tag
-      if (bytesToCopy > maxBytes)
-      {
-        bytesToCopy = maxBytes;
-      }
-
-      for (count = 0; count < bytesToCopy; count++)
-      {
-        buffer[index++] = uid->uidByte[uidIndex + count];
-      }
-    }
-    // Now that the data has been copied we need to include the 8 bits in CT in currentLevelKnownBits
-    if (useCascadeTag)
-    {
-      currentLevelKnownBits += 8;
-    }
-
-    // Repeat anti collision loop until we can transmit all UID bits + BCC and receive a SAK - max 32 iterations.
-    selectDone = false;
-    while ( ! selectDone)
-    {
-      // Find out how many bits and bytes to send and receive.
-      if (currentLevelKnownBits >= 32) { // All UID bits in this Cascade Level are known. This is a SELECT.
-        //Serial.print("SELECT: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
-        buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes
-        // Calulate BCC - Block Check Character
-        buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5];
-        // Calculate CRC_A
-        result = PCD_CalculateCRC(buffer, 7, &buffer[7]);
-        if (result != STATUS_OK)
-        {
-          return result;
-        }
-        txLastBits    = 0; // 0 => All 8 bits are valid.
-        bufferUsed    = 9;
-        // Store response in the last 3 bytes of buffer (BCC and CRC_A - not needed after tx)
-        responseBuffer  = &buffer[6];
-        responseLength  = 3;
-      }
-      else { // This is an ANTICOLLISION.
-        //Serial.print("ANTICOLLISION: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
-        txLastBits    = currentLevelKnownBits % 8;
-        count     = currentLevelKnownBits / 8;  // Number of whole bytes in the UID part.
-        index     = 2 + count;          // Number of whole bytes: SEL + NVB + UIDs
-        buffer[1]   = (index << 4) + txLastBits;  // NVB - Number of Valid Bits
-        bufferUsed    = index + (txLastBits ? 1 : 0);
-        // Store response in the unused part of buffer
-        responseBuffer  = &buffer[index];
-        responseLength  = sizeof(buffer) - index;
-      }
-
-      // Set bit adjustments
-      rxAlign = txLastBits;                     // Having a seperate variable is overkill. But it makes the next line easier to read.
-      PCD_WriteRegister(BitFramingReg, (rxAlign << 4) + txLastBits);  // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
-
-      // Transmit the buffer and receive the response.
-      result = PCD_TransceiveData(buffer, bufferUsed, responseBuffer, &responseLength, &txLastBits, rxAlign);
-      if (result == STATUS_COLLISION) { // More than one PICC in the field => collision.
-        result = PCD_ReadRegister(CollReg); // CollReg[7..0] bits are: ValuesAfterColl reserved CollPosNotValid CollPos[4:0]
-        if (result & 0x20) { // CollPosNotValid
-          return STATUS_COLLISION; // Without a valid collision position we cannot continue
-        }
-        uint8_t collisionPos = result & 0x1F; // Values 0-31, 0 means bit 32.
-        if (collisionPos == 0)
-        {
-          collisionPos = 32;
-        }
-        if (collisionPos <= currentLevelKnownBits) { // No progress - should not happen
-          return STATUS_INTERNAL_ERROR;
-        }
-        // Choose the PICC with the bit set.
-        currentLevelKnownBits = collisionPos;
-        count     = (currentLevelKnownBits - 1) % 8; // The bit to modify
-        index     = 1 + (currentLevelKnownBits / 8) + (count ? 1 : 0); // First byte is index 0.
-        buffer[index] |= (1 << count);
-      }
-      else if (result != STATUS_OK) {
-        return result;
-      }
-      else { // STATUS_OK
-        if (currentLevelKnownBits >= 32) { // This was a SELECT.
-          selectDone = true; // No more anticollision
-          // We continue below outside the while.
-        }
-        else { // This was an ANTICOLLISION.
-          // We now have all 32 bits of the UID in this Cascade Level
-          currentLevelKnownBits = 32;
-          // Run loop again to do the SELECT.
-        }
-      }
-    } // End of while ( ! selectDone)
-
-    // We do not check the CBB - it was constructed by us above.
-
-    // Copy the found UID bytes from buffer[] to uid->uidByte[]
-    index     = (buffer[2] == PICC_CMD_CT) ? 3 : 2; // source index in buffer[]
-    bytesToCopy   = (buffer[2] == PICC_CMD_CT) ? 3 : 4;
-    for (count = 0; count < bytesToCopy; count++)
-    {
-      uid->uidByte[uidIndex + count] = buffer[index++];
-    }
-
-    // Check response SAK (Select Acknowledge)
-    if (responseLength != 3 || txLastBits != 0) {   // SAK must be exactly 24 bits (1 byte + CRC_A).
-      return STATUS_ERROR;
-    }
-    // Verify CRC_A - do our own calculation and store the control in buffer[2..3] - those bytes are not needed anymore.
-    result = PCD_CalculateCRC(responseBuffer, 1, &buffer[2]);
-    if (result != STATUS_OK)
-    {
-      return result;
-    }
-    if ((buffer[2] != responseBuffer[1]) || (buffer[3] != responseBuffer[2]))
-    {
-      return STATUS_CRC_WRONG;
-    }
-    if (responseBuffer[0] & 0x04) { // Cascade bit set - UID not complete yes
-      cascadeLevel++;
-    }
-    else
-    {
-      uidComplete = true;
-      uid->sak = responseBuffer[0];
-    }
-  } // End of while ( ! uidComplete)
-
-  // Set correct uid->size
-  uid->size = 3 * cascadeLevel + 1;
-
-  return STATUS_OK;
-} // End PICC_Select()
-
-/**
- * Instructs a PICC in state ACTIVE(*) to go to state HALT.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PICC_HaltA()
-{
-  uint8_t result;
-  uint8_t buffer[4];
-
-  // Build command buffer
-  buffer[0] = PICC_CMD_HLTA;
-  buffer[1] = 0;
-  // Calculate CRC_A
-  result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  // Send the command.
-  // The standard says:
-  //    If the PICC responds with any modulation during a period of 1 ms after the end of the frame containing the
-  //    HLTA command, this response shall be interpreted as 'not acknowledge'.
-  // We interpret that this way: Only STATUS_TIMEOUT is an success.
-  result = PCD_TransceiveData(buffer, sizeof(buffer), NULL, 0);
-  if (result == STATUS_TIMEOUT)
-  {
-    return STATUS_OK;
-  }
-  if (result == STATUS_OK) { // That is ironically NOT ok in this case ;-)
-    return STATUS_ERROR;
-  }
-  return result;
-} // End PICC_HaltA()
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for communicating with MIFARE PICCs
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Executes the MFRC522 MFAuthent command.
- * This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.
- * The authentication is described in the MFRC522 datasheet section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1.
- * For use with MIFARE Classic PICCs.
- * The PICC must be selected - ie in state ACTIVE(*) - before calling this function.
- * Remember to call PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise no new communications can start.
- *
- * All keys are set to FFFFFFFFFFFFh at chip delivery.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.
- */
-uint8_t MFRC522::PCD_Authenticate(uint8_t command, uint8_t blockAddr, MIFARE_Key *key, Uid *uid)
-{
-  uint8_t waitIRq = 0x10;    // IdleIRq
-
-  // Build command buffer
-  uint8_t sendData[12];
-  sendData[0] = command;
-  sendData[1] = blockAddr;
-  for (uint8_t i = 0; i < MF_KEY_SIZE; i++) {  // 6 key bytes
-    sendData[2+i] = key->keyByte[i];
-  }
-  for (uint8_t i = 0; i < 4; i++) {        // The first 4 bytes of the UID
-    sendData[8+i] = uid->uidByte[i];
-  }
-
-  // Start the authentication.
-  return PCD_CommunicateWithPICC(PCD_MFAuthent, waitIRq, &sendData[0], sizeof(sendData));
-} // End PCD_Authenticate()
-
-/**
- * Used to exit the PCD from its authenticated state.
- * Remember to call this function after communicating with an authenticated PICC - otherwise no new communications can start.
- */
-void MFRC522::PCD_StopCrypto1()
-{
-  // Clear MFCrypto1On bit
-  PCD_ClearRegisterBitMask(Status2Reg, 0x08); // Status2Reg[7..0] bits are: TempSensClear I2CForceHS reserved reserved   MFCrypto1On ModemState[2:0]
-} // End PCD_StopCrypto1()
-
-/**
- * Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight only addresses 00h to 0Fh are decoded.
- * The MF0ICU1 returns a NAK for higher addresses.
- * The MF0ICU1 responds to the READ command by sending 16 bytes starting from the page address defined by the command argument.
- * For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned.
- * A roll-back is implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are returned.
- *
- * The buffer must be at least 18 bytes because a CRC_A is also returned.
- * Checks the CRC_A before returning STATUS_OK.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Read(uint8_t blockAddr, uint8_t *buffer, uint8_t *bufferSize)
-{
-  uint8_t result;
-
-  // Sanity check
-  if (buffer == NULL || *bufferSize < 18)
-  {
-    return STATUS_NO_ROOM;
-  }
-
-  // Build command buffer
-  buffer[0] = PICC_CMD_MF_READ;
-  buffer[1] = blockAddr;
-  // Calculate CRC_A
-  result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  // Transmit the buffer and receive the response, validate CRC_A.
-  return PCD_TransceiveData(buffer, 4, buffer, bufferSize, NULL, 0, true);
-} // End MIFARE_Read()
-
-/**
- * Writes 16 bytes to the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight the opretaion is called "COMPATIBILITY WRITE".
- * Even though 16 bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes 0 to 3)
- * are written to the specified address. It is recommended to set the remaining bytes 04h to 0Fh to all logic 0.
- * *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Write(uint8_t blockAddr, uint8_t *buffer, uint8_t bufferSize)
-{
-  uint8_t result;
-
-  // Sanity check
-  if (buffer == NULL || bufferSize < 16)
-  {
-    return STATUS_INVALID;
-  }
-
-  // Mifare Classic protocol requires two communications to perform a write.
-  // Step 1: Tell the PICC we want to write to block blockAddr.
-  uint8_t cmdBuffer[2];
-  cmdBuffer[0] = PICC_CMD_MF_WRITE;
-  cmdBuffer[1] = blockAddr;
-  result = PCD_MIFARE_Transceive(cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  // Step 2: Transfer the data
-  result = PCD_MIFARE_Transceive( buffer, bufferSize); // Adds CRC_A and checks that the response is MF_ACK.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  return STATUS_OK;
-} // End MIFARE_Write()
-
-/**
- * Writes a 4 byte page to the active MIFARE Ultralight PICC.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Ultralight_Write(uint8_t page, uint8_t *buffer, uint8_t bufferSize)
-{
-  uint8_t result;
-
-  // Sanity check
-  if (buffer == NULL || bufferSize < 4)
-  {
-    return STATUS_INVALID;
-  }
-
-  // Build commmand buffer
-  uint8_t cmdBuffer[6];
-  cmdBuffer[0] = PICC_CMD_UL_WRITE;
-  cmdBuffer[1] = page;
-  memcpy(&cmdBuffer[2], buffer, 4);
-
-  // Perform the write
-  result = PCD_MIFARE_Transceive(cmdBuffer, 6); // Adds CRC_A and checks that the response is MF_ACK.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-  return STATUS_OK;
-} // End MIFARE_Ultralight_Write()
-
-/**
- * MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Decrement(uint8_t blockAddr, uint32_t delta)
-{
-  return MIFARE_TwoStepHelper(PICC_CMD_MF_DECREMENT, blockAddr, delta);
-} // End MIFARE_Decrement()
-
-/**
- * MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Increment(uint8_t blockAddr, uint32_t delta)
-{
-  return MIFARE_TwoStepHelper(PICC_CMD_MF_INCREMENT, blockAddr, delta);
-} // End MIFARE_Increment()
-
-/**
- * MIFARE Restore copies the value of the addressed block into a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Restore(uint8_t blockAddr)
-{
-  // The datasheet describes Restore as a two step operation, but does not explain what data to transfer in step 2.
-  // Doing only a single step does not work, so I chose to transfer 0L in step two.
-  return MIFARE_TwoStepHelper(PICC_CMD_MF_RESTORE, blockAddr, 0L);
-} // End MIFARE_Restore()
-
-/**
- * Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, uint32_t data)
-{
-  uint8_t result;
-  uint8_t cmdBuffer[2]; // We only need room for 2 bytes.
-
-  // Step 1: Tell the PICC the command and block address
-  cmdBuffer[0] = command;
-  cmdBuffer[1] = blockAddr;
-  result = PCD_MIFARE_Transceive( cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  // Step 2: Transfer the data
-  result = PCD_MIFARE_Transceive((uint8_t *) &data, 4, true); // Adds CRC_A and accept timeout as success.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  return STATUS_OK;
-} // End MIFARE_TwoStepHelper()
-
-/**
- * MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::MIFARE_Transfer(uint8_t blockAddr)
-{
-  uint8_t result;
-  uint8_t cmdBuffer[2]; // We only need room for 2 bytes.
-
-  // Tell the PICC we want to transfer the result into block blockAddr.
-  cmdBuffer[0] = PICC_CMD_MF_TRANSFER;
-  cmdBuffer[1] = blockAddr;
-  result = PCD_MIFARE_Transceive( cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-  return STATUS_OK;
-} // End MIFARE_Transfer()
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Support functions
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Wrapper for MIFARE protocol communication.
- * Adds CRC_A, executes the Transceive command and checks that the response is MF_ACK or a timeout.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-uint8_t MFRC522::PCD_MIFARE_Transceive(uint8_t *sendData, uint8_t sendLen, bool acceptTimeout)
-{
-  uint8_t result;
-  uint8_t cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A.
-
-  // Sanity check
-  if (sendData == NULL || sendLen > 16)
-  {
-    return STATUS_INVALID;
-  }
-
-  // Copy sendData[] to cmdBuffer[] and add CRC_A
-  memcpy(cmdBuffer, sendData, sendLen);
-  result = PCD_CalculateCRC(cmdBuffer, sendLen, &cmdBuffer[sendLen]);
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-  sendLen += 2;
-
-  // Transceive the data, store the reply in cmdBuffer[]
-  uint8_t waitIRq = 0x30;    // RxIRq and IdleIRq
-  uint8_t cmdBufferSize = sizeof(cmdBuffer);
-  uint8_t validBits = 0;
-  result = PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, cmdBuffer, sendLen, cmdBuffer, &cmdBufferSize, &validBits);
-  if (acceptTimeout && result == STATUS_TIMEOUT)
-  {
-    return STATUS_OK;
-  }
-
-  if (result != STATUS_OK)
-  {
-    return result;
-  }
-
-  // The PICC must reply with a 4 bit ACK
-  if (cmdBufferSize != 1 || validBits != 4)
-  {
-    return STATUS_ERROR;
-  }
-
-  if (cmdBuffer[0] != MF_ACK)
-  {
-    return STATUS_MIFARE_NACK;
-  }
-
-  return STATUS_OK;
-} // End PCD_MIFARE_Transceive()
-
-
-/**
- * Translates the SAK (Select Acknowledge) to a PICC type.
- *
- * @return PICC_Type
- */
-uint8_t MFRC522::PICC_GetType(uint8_t sak)
-{
-  uint8_t retType = PICC_TYPE_UNKNOWN;
-  
-  if (sak & 0x04)  // UID not complete
-  {
-    retType = PICC_TYPE_NOT_COMPLETE;
-  }
-  else
-  {
-    switch (sak)
-    {
-      case 0x09: retType = PICC_TYPE_MIFARE_MINI; break;
-      case 0x08: retType = PICC_TYPE_MIFARE_1K;   break;
-      case 0x18: retType = PICC_TYPE_MIFARE_4K;   break;
-      case 0x00: retType = PICC_TYPE_MIFARE_UL;   break;
-      case 0x10:
-      case 0x11: retType = PICC_TYPE_MIFARE_PLUS; break;
-      case 0x01: retType = PICC_TYPE_TNP3XXX;     break;
-      default:   
-        if (sak & 0x20)
-        {
-          retType = PICC_TYPE_ISO_14443_4;
-        }
-        else if (sak & 0x40)
-        {
-          retType = PICC_TYPE_ISO_18092;
-        }
-        break;
-    }
-  }
-
-  return (retType);
-} // End PICC_GetType()
-
-/**
- * Returns a string pointer to the PICC type name.
- *
- */
-std::string MFRC522::PICC_GetTypeName(uint8_t piccType)
-{
-  if(piccType == PICC_TYPE_NOT_COMPLETE)
-  {
-    return ("SAK indicates UID is not complete.");
-  }
-
-  return(_TypeNamePICC[piccType]);
-} // End PICC_GetTypeName()
-
-/**
- * Returns a string pointer to a status code name.
- *
- */
-std::string MFRC522::GetStatusCodeName(uint8_t code)
-{
-  return(_ErrorMessage[code]);
-} // End GetStatusCodeName()
-
-/**
- * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tupples C1 is MSB (=4) and C3 is LSB (=1).
- */
-void MFRC522::MIFARE_SetAccessBits(uint8_t *accessBitBuffer,  ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
-                                   uint8_t g0,                ///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
-                                   uint8_t g1,                ///< Access bits C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
-                                   uint8_t g2,                ///< Access bits C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
-                                   uint8_t g3)                ///< Access bits C1 C2 C3] for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
-{
-  uint8_t c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2);
-  uint8_t c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1);
-  uint8_t c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0);
-
-  accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF);
-  accessBitBuffer[1] =          c1 << 4 | (~c3 & 0xF);
-  accessBitBuffer[2] =          c3 << 4 | c2;
-} // End MIFARE_SetAccessBits()
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Convenience functions - does not add extra functionality
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Returns true if a PICC responds to PICC_CMD_REQA.
- * Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.
- *
- * @return bool
- */
-bool MFRC522::PICC_IsNewCardPresent()
-{
-  uint8_t bufferATQA[2];
-  uint8_t bufferSize = sizeof(bufferATQA);
-  uint8_t result = PICC_RequestA(bufferATQA, &bufferSize);
-  return (result == STATUS_OK || result == STATUS_COLLISION);
-} // End PICC_IsNewCardPresent()
-
-/**
- * Simple wrapper around PICC_Select.
- * Returns true if a UID could be read.
- * Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() first.
- * The read UID is available in the class variable uid.
- *
- * @return bool
- */
-bool MFRC522::PICC_ReadCardSerial()
-{
-  uint8_t result = PICC_Select(&uid);
-  return (result == STATUS_OK);
-} // End PICC_ReadCardSerial()
diff -r 1d9c7c0b5015 -r 8e41a7b03f45 MFRC522.h
--- a/MFRC522.h	Sat Dec 14 21:41:08 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/**
- * MFRC522.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
- * Based on code Dr.Leong   ( WWW.B2CQSHOP.COM )
- * Created by Miguel Balboa (circuitito.com), Jan, 2012.
- * Rewritten by S�ren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
- * Ported by Martin Olejar to mbed, Dec, 2013
- *
- * Please read this file for an overview and then MFRC522.cpp for comments on the specific functions.
- * Search for "mf-rc522" on ebay.com to purchase the MF-RC522 board.
- *
- * There are three hardware components involved:
- * 1) The micro controller: An Arduino
- * 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
- * 3) The PICC (short for Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
- *
- * The microcontroller and card reader uses SPI for communication.
- * The protocol is described in the MFRC522 datasheet: http://www.nxp.com/documents/data_sheet/MFRC522.pdf
- *
- * The card reader and the tags communicate using a 13.56MHz electromagnetic field.
- * The protocol is defined in ISO/IEC 14443-3 Identification cards -- Contactless integrated circuit cards -- Proximity cards -- Part 3: Initialization and anticollision".
- * A free version of the final draft can be found at http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf
- * Details are found in chapter 6, Type A � Initialization and anticollision.
- *
- * If only the PICC UID is wanted, the above documents has all the needed information.
- * To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has been selected.
- * The MIFARE Classic chips and protocol is described in the datasheets:
- *    1K:   http://www.nxp.com/documents/data_sheet/MF1S503x.pdf
- *    4K:   http://www.nxp.com/documents/data_sheet/MF1S703x.pdf
- *    Mini: http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf
- * The MIFARE Ultralight chip and protocol is described in the datasheets:
- *    Ultralight:   http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf
- *    Ultralight C: http://www.nxp.com/documents/short_data_sheet/MF0ICU2_SDS.pdf
- *
- * MIFARE Classic 1K (MF1S503x):
- *    Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
- *    The blocks are numbered 0-63.
- *    Block 3 in each sector is the Sector Trailer. See http://www.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)
- *    Block 0 is read only manufacturer data.
- *    To access a block, an authentication using a key from the block's sector must be performed first.
- *    Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11).
- *    All keys are set to FFFFFFFFFFFFh at chip delivery.
- *    Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked.
- *    To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns.
- * MIFARE Classic 4K (MF1S703x):
- *    Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
- *    The blocks are numbered 0-255.
- *    The last block in each sector is the Sector Trailer like above.
- * MIFARE Classic Mini (MF1 IC S20):
- *    Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
- *    The blocks are numbered 0-19.
- *    The last block in each sector is the Sector Trailer like above.
- *
- * MIFARE Ultralight (MF0ICU1):
- *    Has 16 pages of 4 bytes = 64 bytes.
- *    Pages 0 + 1 is used for the 7-byte UID.
- *    Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
- *    Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
- *    Pages 4-15 are read/write unless blocked by the lock bytes in page 2.
- * MIFARE Ultralight C (MF0ICU2):
- *    Has 48 pages of 4 bytes = 64 bytes.
- *    Pages 0 + 1 is used for the 7-byte UID.
- *    Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
- *    Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
- *    Pages 4-39 are read/write unless blocked by the lock bytes in page 2.
- *    Page 40 Lock bytes
- *    Page 41 16 bit one way counter
- *    Pages 42-43 Authentication configuration
- *    Pages 44-47 Authentication key
- */
-#ifndef MFRC522_h
-#define MFRC522_h
-
-#include <string>
-#include "mbed.h"
-
-class MFRC522 {
-public:
-
-  // 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 {
-    // 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,
-    TCntValueRegH   = 0x2E << 1,  // shows the 16-bit timer value
-    TCntValueRegL   = 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 {
-    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
-  };
-
-  // Commands sent to the PICC.
-  enum PICC_Command {
-    // 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 1
-    PICC_CMD_SEL_CL3       = 0x97,   // Anti collision/Select, Cascade Level 1
-    PICC_CMD_HLTA          = 0x50,   // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
-    // The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.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.
-  enum PICC_Type {
-    PICC_TYPE_UNKNOWN      = 0,
-    PICC_TYPE_ISO_14443_4  = 1,  // PICC compliant with ISO/IEC 14443-4
-    PICC_TYPE_ISO_18092    = 2,  // PICC compliant with ISO/IEC 18092 (NFC)
-    PICC_TYPE_MIFARE_MINI  = 3,  // MIFARE Classic protocol, 320 bytes
-    PICC_TYPE_MIFARE_1K    = 4,  // MIFARE Classic protocol, 1KB
-    PICC_TYPE_MIFARE_4K    = 5,  // MIFARE Classic protocol, 4KB
-    PICC_TYPE_MIFARE_UL    = 6,  // MIFARE Ultralight or Ultralight C
-    PICC_TYPE_MIFARE_PLUS  = 7,  // MIFARE Plus
-    PICC_TYPE_TNP3XXX      = 8,  // Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
-    PICC_TYPE_NOT_COMPLETE = 255 // SAK indicates UID is not complete.
-  };
-
-  // Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
-  enum StatusCode {
-    STATUS_OK              = 1,  // Success
-    STATUS_ERROR           = 2,  // Error in communication
-    STATUS_COLLISION       = 3,  // Collision detected
-    STATUS_TIMEOUT         = 4,  // Timeout in communication.
-    STATUS_NO_ROOM         = 5,  // A buffer is not big enough.
-    STATUS_INTERNAL_ERROR  = 6,  // Internal error in the code. Should not happen ;-)
-    STATUS_INVALID         = 7,  // Invalid argument.
-    STATUS_CRC_WRONG       = 8,  // The CRC_A does not match
-    STATUS_MIFARE_NACK     = 9   // A MIFARE PICC responded with NAK.
-  };
-
-  // A struct used for passing the UID of a PICC.
-  typedef struct {
-    uint8_t    size;     // Number of bytes in the UID. 4, 7 or 10.
-    uint8_t    uidByte[10];
-    uint8_t    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 {
-    uint8_t    keyByte[MF_KEY_SIZE];
-  } MIFARE_Key;
-
-  // Member variables
-  Uid uid;                // Used by PICC_ReadCardSerial().
-
-  // Size of the MFRC522 FIFO
-  static const uint8_t FIFO_SIZE = 64;   // The FIFO is 64 bytes.
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Functions for setting up the driver
-  /////////////////////////////////////////////////////////////////////////////////////
-  MFRC522(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Functions for manipulating the MFRC522
-  /////////////////////////////////////////////////////////////////////////////////////
-  void PCD_Init();
-  void PCD_Reset();
-  void PCD_AntennaOn();
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Basic interface functions for communicating with the MFRC522
-  /////////////////////////////////////////////////////////////////////////////////////
-  void    PCD_WriteRegister(uint8_t reg, uint8_t value);
-  void    PCD_WriteRegister(uint8_t reg, uint8_t count, uint8_t *values);
-  uint8_t PCD_ReadRegister(uint8_t reg);
-  void    PCD_ReadRegister(uint8_t reg, uint8_t count, uint8_t *values, uint8_t rxAlign = 0);
-  void    PCD_SetRegisterBitMask(uint8_t reg, uint8_t mask);
-  void    PCD_ClearRegisterBitMask(uint8_t reg, uint8_t mask);
-  uint8_t PCD_CalculateCRC(uint8_t *data, uint8_t length, uint8_t *result);
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Functions for communicating with PICCs
-  /////////////////////////////////////////////////////////////////////////////////////
-  uint8_t PCD_TransceiveData(uint8_t *sendData, uint8_t sendLen, uint8_t *backData, uint8_t *backLen, uint8_t *validBits = NULL, uint8_t rxAlign = 0, bool checkCRC = false);
-  uint8_t PCD_CommunicateWithPICC(uint8_t command, uint8_t waitIRq, uint8_t *sendData, uint8_t sendLen, uint8_t *backData = NULL, uint8_t *backLen = NULL, uint8_t *validBits = NULL, uint8_t rxAlign = 0, bool checkCRC = false);
-
-  uint8_t PICC_RequestA(uint8_t *bufferATQA, uint8_t *bufferSize);
-  uint8_t PICC_WakeupA(uint8_t *bufferATQA, uint8_t *bufferSize);
-  uint8_t PICC_REQA_or_WUPA(uint8_t command, uint8_t *bufferATQA, uint8_t *bufferSize);
-  uint8_t PICC_Select(Uid *uid, uint8_t validBits = 0);
-  uint8_t PICC_HaltA();
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Functions for communicating with MIFARE PICCs
-  /////////////////////////////////////////////////////////////////////////////////////
-  uint8_t PCD_Authenticate(uint8_t command, uint8_t blockAddr, MIFARE_Key *key, Uid *uid);
-  void    PCD_StopCrypto1();
-  uint8_t MIFARE_Read(uint8_t blockAddr, uint8_t *buffer, uint8_t *bufferSize);
-  uint8_t MIFARE_Write(uint8_t blockAddr, uint8_t *buffer, uint8_t bufferSize);
-  uint8_t MIFARE_Decrement(uint8_t blockAddr, uint32_t delta);
-  uint8_t MIFARE_Increment(uint8_t blockAddr, uint32_t delta);
-  uint8_t MIFARE_Restore(uint8_t blockAddr);
-  uint8_t MIFARE_Transfer(uint8_t blockAddr);
-  uint8_t MIFARE_Ultralight_Write(uint8_t page, uint8_t *buffer, uint8_t bufferSize);
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Support functions
-  /////////////////////////////////////////////////////////////////////////////////////
-  uint8_t PCD_MIFARE_Transceive(uint8_t *sendData, uint8_t sendLen, bool acceptTimeout = false);
-  uint8_t PICC_GetType(uint8_t sak);
-  std::string PICC_GetTypeName(uint8_t type);
-  std::string GetStatusCodeName(uint8_t code);
-  void MIFARE_SetAccessBits(uint8_t *accessBitBuffer, uint8_t g0, uint8_t g1, uint8_t g2, uint8_t g3);
-
-  /////////////////////////////////////////////////////////////////////////////////////
-  // Convenience functions - does not add extra functionality
-  /////////////////////////////////////////////////////////////////////////////////////
-  bool PICC_IsNewCardPresent();
-  bool PICC_ReadCardSerial();
-
-private:
-  SPI              m_SPI;
-  DigitalOut       m_CS;
-  DigitalOut       m_RESET;
-
-  uint8_t MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, uint32_t data);
-};
-
-#endif
diff -r 1d9c7c0b5015 -r 8e41a7b03f45 MFRC522.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MFRC522.lib	Wed Dec 18 00:46:40 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AtomX/code/MFRC522/#efd786b99a72
diff -r 1d9c7c0b5015 -r 8e41a7b03f45 main.cpp
--- a/main.cpp	Sat Dec 14 21:41:08 2013 +0000
+++ b/main.cpp	Wed Dec 18 00:46:40 2013 +0000
@@ -1,46 +1,49 @@
 #include "mbed.h"
 #include "MFRC522.h"
 
-#define BOARD_KL25Z     1
-//#define BOARD_LPC11U24  1
-
-
-#if defined(BOARD_KL25Z)
+#if defined(TARGET_KL25Z)
 
 /* KL25Z Pins for MFRC522 SPI interface */
-#define SPI_MOSI    PTA16
-#define SPI_MISO    PTA17
-#define SPI_SCLK    PTD1
-#define SPI_CS      PTD3
+#define SPI_MOSI    PTC6
+#define SPI_MISO    PTC7
+#define SPI_SCLK    PTC5
+#define SPI_CS      PTC4
 
 /* KL25Z Pin for MFRC522 reset */
-#define MF_RESET    PTD2
+#define MF_RESET    PTC3
 
 /* KL25Z Pins for UART Debug port */
 #define UART_RX     PTA1
 #define UART_TX     PTA2
 
-#elif defined(BOARD_LPC11U24)
+#elif defined(TARGET_LPC11U24)
 
 /* LPC11U24 Pins for MFRC522 SPI interface */
-#define SPI_MOSI    p16
-#define SPI_MISO    p15
-#define SPI_SCLK    p13
-#define SPI_CS      p34
+#define SPI_MOSI    P0_9
+#define SPI_MISO    P0_8
+#define SPI_SCLK    P1_29
+#define SPI_CS      P0_2
 
 /* LPC11U24 Pin for MFRC522 reset */
-#define MF_RESET    p17
+#define MF_RESET    P1_13
 
 /* LPC11U24 Pins for UART Debug port */
-#define UART_RX     p20
-#define UART_TX     p19
+#define UART_RX     P0_18
+#define UART_TX     P0_19
+
+/* LED Pins */
+#define LED_RED     P0_7
+#define LED_GREEN   P1_22
 
 #endif
 
-Serial  DebugUART   (UART_TX, UART_RX);
-MFRC522 RfChip      (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET);
+DigitalOut LedRed   (LED_RED);
+DigitalOut LedGreen (LED_GREEN);
 
+Serial     DebugUART(UART_TX, UART_RX);
+MFRC522    RfChip   (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET);
 
+/* Local functions */
 void DumpMifareClassicToSerial      (MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key);
 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector);
 void DumpMifareUltralightToSerial   (void);
@@ -55,7 +58,7 @@
   MFRC522::MIFARE_Key key;
 
   // UID
-  printf("Card UID:");
+  printf("Card UID: ");
   for (uint8_t i = 0; i < uid->size; i++)
   {
     printf(" %X02", uid->uidByte[i]);
@@ -64,7 +67,7 @@
 
   // PICC type
   uint8_t piccType = RfChip.PICC_GetType(uid->sak);
-  printf("PICC type: %s \n\r", RfChip.PICC_GetTypeName(piccType).c_str());
+  printf("PICC Type: %s \n\r", RfChip.PICC_GetTypeName(piccType));
 
 
   // Dump contents
@@ -74,10 +77,7 @@
     case MFRC522::PICC_TYPE_MIFARE_1K:
     case MFRC522::PICC_TYPE_MIFARE_4K:
       // All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
-      for (uint8_t i = 0; i < 6; i++)
-      {
-        key.keyByte[i] = 0xFF;
-      }
+      for (uint8_t i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; }
       DumpMifareClassicToSerial(uid, piccType, &key);
       break;
 
@@ -127,15 +127,17 @@
       no_of_sectors = 40;
       break;
 
-    default: // Should not happen. Ignore.
+    default:
+      // Should not happen. Ignore.
       break;
   }
 
   // Dump sectors, highest address first.
   if (no_of_sectors)
   {
-    printf("Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits \n\r");
-    for (uint8_t i = no_of_sectors - 1; i >= 0; i--)
+    printf("Sector  Block   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  AccessBits \n\r");
+    printf("----------------------------------------------------------------------------------------- \n\r");
+    for (uint8_t i = no_of_sectors - 1; i > 0; i--)
     {
       DumpMifareClassicSectorToSerial(uid, key, i);
     }
@@ -167,7 +169,7 @@
   // The four CX bits are stored together in a nible cx and an inverted nible cx_.
   uint8_t c1, c2, c3;      // Nibbles
   uint8_t c1_, c2_, c3_;   // Inverted nibbles
-  bool    invertedError;   // True if one of the inverted nibbles did not match
+  bool    invertedError = false;   // True if one of the inverted nibbles did not match
   uint8_t g[4];            // Access bits for each of the four groups.
   uint8_t group;           // 0-3 - active group for access bits
   bool    firstInGroup;    // True for the first block dumped in the group
@@ -193,9 +195,10 @@
   uint8_t buffer[18];
   uint8_t blockAddr;
   isSectorTrailer = true;
-  for (char blockOffset = no_of_blocks - 1; blockOffset >= 0; blockOffset--)
+  for (uint8_t blockOffset = no_of_blocks - 1; blockOffset > 0; blockOffset--)
   {
     blockAddr = firstBlock + blockOffset;
+
     // Sector number - only on first line
     if (isSectorTrailer)
     {
@@ -205,35 +208,40 @@
     {
       printf("       ");
     }
+
     // Block number
-    printf("  %3d  ", blockAddr);
+    printf(" %3d  ", blockAddr);
+
     // Establish encrypted communications before reading the first block
     if (isSectorTrailer)
     {
       status = RfChip.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid);
       if (status != MFRC522::STATUS_OK)
       {
-        printf("PCD_Authenticate() failed: %s \r\n", RfChip.GetStatusCodeName(status).c_str());
+        printf("PCD_Authenticate() failed: %s \r\n", RfChip.GetStatusCodeName(status));
         return;
       }
     }
+
     // Read block
     byteCount = sizeof(buffer);
     status = RfChip.MIFARE_Read(blockAddr, buffer, &byteCount);
     if (status != MFRC522::STATUS_OK)
     {
-      printf("MIFARE_Read() failed: %s \r\n", RfChip.GetStatusCodeName(status).c_str());
+      printf("MIFARE_Read() failed: %s \r\n", RfChip.GetStatusCodeName(status));
       continue;
     }
+
     // Dump data
     for (uint8_t index = 0; index < 16; index++)
     {
-      printf(" %2d", buffer[index]);
-      if ((index % 4) == 3)
-      {
-        printf(" ");
-      }
+      printf(" %3d", buffer[index]);
+//      if ((index % 4) == 3)
+//      {
+//        printf(" ");
+//      }
     }
+
     // Parse sector trailer data
     if (isSectorTrailer)
     {
@@ -244,7 +252,7 @@
       c2_ = buffer[6] >> 4;
       c3_ = buffer[7] & 0xF;
       invertedError = (c1 != (~c1_ & 0xF)) || (c2 != (~c2_ & 0xF)) || (c3 != (~c3_ & 0xF));
-      
+
       g[0] = ((c1 & 1) << 2) | ((c2 & 1) << 1) | ((c3 & 1) << 0);
       g[1] = ((c1 & 2) << 1) | ((c2 & 2) << 0) | ((c3 & 2) >> 1);
       g[2] = ((c1 & 4) << 0) | ((c2 & 4) >> 1) | ((c3 & 4) >> 2);
@@ -267,7 +275,7 @@
     if (firstInGroup)
     {
       // Print access bits
-      printf(" [ %d %d %d ] ", (g[group] >> 2) & 1, (g[group] >> 1) & 1, (g[group] >> 0) & 1);
+      printf("   [ %d %d %d ] ", (g[group] >> 2) & 1, (g[group] >> 1) & 1, (g[group] >> 0) & 1);
       if (invertedError)
       {
         printf(" Inverted access bits did not match! ");
@@ -299,7 +307,7 @@
   uint8_t buffer[18];
   uint8_t i;
 
-  printf("Page  0  1  2  3");
+  printf("Page   0  1  2  3");
   // Try the mpages of the original Ultralight. Ultralight C has more pages.
   for (uint8_t page = 0; page < 16; page +=4)
   {
@@ -308,7 +316,7 @@
     status = RfChip.MIFARE_Read(page, buffer, &byteCount);
     if (status != MFRC522::STATUS_OK)
     {
-      printf("MIFARE_Read() failed: %s \n\r", RfChip.GetStatusCodeName(status).c_str());
+      printf("MIFARE_Read() failed: %s \n\r", RfChip.GetStatusCodeName(status));
       break;
     }
 
@@ -316,7 +324,7 @@
     for (uint8_t offset = 0; offset < 4; offset++)
     {
       i = page + offset;
-      printf(" %2d ", i); // Pad with spaces
+      printf(" %2d  ", i); // Pad with spaces
       for (uint8_t index = 0; index < 4; index++)
       {
         i = 4 * offset + index;
@@ -330,25 +338,45 @@
 
 int main()
 {
+  /* Set debug UART speed */
   DebugUART.baud(115200);
+  printf("< mbed RFID demo >\n\r");
+  printf("\n\r");
 
+  /* Init. RC522 Chip */
   RfChip.PCD_Init();
 
+  /* Read RC522 version */
+  uint8_t temp = RfChip.PCD_ReadRegister(MFRC522::VersionReg);
+  printf("MFRC522 version: %d\n\r", temp & 0x07);
+  printf("\n\r");
+
   while(1)
   {
+    LedRed   = 1;
+    LedGreen = 1;
+
     // Look for new cards
     if ( ! RfChip.PICC_IsNewCardPresent())
     {
+      wait_ms(500);
       continue;
     }
 
+    LedRed   = 0;
+
     // Select one of the cards
     if ( ! RfChip.PICC_ReadCardSerial())
     {
+      wait_ms(500);
       continue;
     }
 
+    LedRed   = 1;
+    LedGreen = 0;
+
     // Dump debug info about the card. PICC_HaltA() is automatically called.
     DumpToSerial(&(RfChip.uid));
+    wait_ms(200);
   }
 }
diff -r 1d9c7c0b5015 -r 8e41a7b03f45 mbed.bld
--- a/mbed.bld	Sat Dec 14 21:41:08 2013 +0000
+++ b/mbed.bld	Wed Dec 18 00:46:40 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/a9913a65894f
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/a842253909c9
\ No newline at end of file