DANIE BRINK / MFRC522

Dependents:   FRDM_MFRC522

Fork of MFRC522 by Martin Olejar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MFRC522.cpp Source File

MFRC522.cpp

00001 /*
00002 * MFRC522.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
00003 * _Please_ see the comments in MFRC522.h - they give useful hints and background.
00004 * Released into the public domain.
00005 */
00006 
00007 #include "MFRC522.h"
00008 
00009 static const char* const _TypeNamePICC[] =
00010 {
00011   "Unknown type",
00012   "PICC compliant with ISO/IEC 14443-4",
00013   "PICC compliant with ISO/IEC 18092 (NFC)",
00014   "MIFARE Mini, 320 bytes",
00015   "MIFARE 1KB",
00016   "MIFARE 4KB",
00017   "MIFARE Ultralight or Ultralight C",
00018   "MIFARE Plus",
00019   "MIFARE TNP3XXX",
00020 
00021   /* not complete UID */
00022   "SAK indicates UID is not complete"
00023 };
00024 
00025 static const char* const _ErrorMessage[] =
00026 {
00027   "Unknown error",
00028   "Success",
00029   "Error in communication",
00030   "Collision detected",
00031   "Timeout in communication",
00032   "A buffer is not big enough",
00033   "Internal error in the code, should not happen",
00034   "Invalid argument",
00035   "The CRC_A does not match",
00036   "A MIFARE PICC responded with NAK"
00037 };
00038 
00039 #define MFRC522_MaxPICCs (sizeof(_TypeNamePICC)/sizeof(_TypeNamePICC[0]))
00040 #define MFRC522_MaxError (sizeof(_ErrorMessage)/sizeof(_ErrorMessage[0]))
00041 
00042 /////////////////////////////////////////////////////////////////////////////////////
00043 // Functions for setting up the driver
00044 /////////////////////////////////////////////////////////////////////////////////////
00045 
00046 /**
00047  * Constructor.
00048  * Prepares the output pins.
00049  */
00050 MFRC522::MFRC522(PinName mosi,
00051                  PinName miso,
00052                  PinName sclk,
00053                  PinName cs,
00054                  PinName reset) : m_SPI(mosi, miso, sclk), m_CS(cs), m_RESET(reset)
00055 {
00056   /* Configure SPI bus */
00057   m_SPI.format(8, 0);
00058 #if defined(TARGET_NUCLEO_F446ZE)
00059   m_SPI.frequency(20000000);
00060 #else
00061   m_SPI.frequency(8000000);
00062 #endif
00063 
00064   /* Release SPI-CS pin */
00065   m_CS       = 1;
00066 
00067   /* Release RESET pin */
00068   m_RESET    = 1;
00069 } // End constructor
00070 
00071 
00072 /**
00073  * Destructor.
00074  */
00075 MFRC522::~MFRC522()
00076 {
00077 
00078 }
00079 
00080 
00081 /////////////////////////////////////////////////////////////////////////////////////
00082 // Basic interface functions for communicating with the MFRC522
00083 /////////////////////////////////////////////////////////////////////////////////////
00084 
00085 /**
00086  * Writes a byte to the specified register in the MFRC522 chip.
00087  * The interface is described in the datasheet section 8.1.2.
00088  */
00089 void MFRC522::PCD_WriteRegister(uint8_t reg, uint8_t value)
00090 {
00091   m_CS = 0; /* Select SPI Chip MFRC522 */
00092 
00093   // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
00094   (void) m_SPI.write(reg & 0x7E);
00095   (void) m_SPI.write(value);
00096 
00097   m_CS = 1; /* Release SPI Chip MFRC522 */
00098 } // End PCD_WriteRegister()
00099 
00100 /**
00101  * Writes a number of bytes to the specified register in the MFRC522 chip.
00102  * The interface is described in the datasheet section 8.1.2.
00103  */
00104 void MFRC522::PCD_WriteRegister(uint8_t reg, uint8_t count, uint8_t *values)
00105 {
00106   m_CS = 0; /* Select SPI Chip MFRC522 */
00107 
00108   // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
00109   (void) m_SPI.write(reg & 0x7E);
00110   for (uint8_t index = 0; index < count; index++)
00111   {
00112     (void) m_SPI.write(values[index]);
00113   }
00114 
00115   m_CS = 1; /* Release SPI Chip MFRC522 */
00116 } // End PCD_WriteRegister()
00117 
00118 /**
00119  * Reads a byte from the specified register in the MFRC522 chip.
00120  * The interface is described in the datasheet section 8.1.2.
00121  */
00122 uint8_t MFRC522::PCD_ReadRegister(uint8_t reg)
00123 {
00124   uint8_t value;
00125   m_CS = 0; /* Select SPI Chip MFRC522 */
00126 
00127   // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
00128   (void) m_SPI.write(0x80 | reg);
00129 
00130   // Read the value back. Send 0 to stop reading.
00131   value = m_SPI.write(0);
00132 
00133   m_CS = 1; /* Release SPI Chip MFRC522 */
00134 
00135   return value;
00136 } // End PCD_ReadRegister()
00137 
00138 /**
00139  * Reads a number of bytes from the specified register in the MFRC522 chip.
00140  * The interface is described in the datasheet section 8.1.2.
00141  */
00142 void MFRC522::PCD_ReadRegister(uint8_t reg, uint8_t count, uint8_t *values, uint8_t rxAlign)
00143 {
00144   if (count == 0) { return; }
00145 
00146   uint8_t address = 0x80 | reg;  // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
00147   uint8_t index = 0;             // Index in values array.
00148 
00149   m_CS = 0;                      /* Select SPI Chip MFRC522 */
00150   count--;                       // One read is performed outside of the loop
00151   (void) m_SPI.write(address);   // Tell MFRC522 which address we want to read
00152 
00153   while (index < count)
00154   {
00155     if ((index == 0) && rxAlign) // Only update bit positions rxAlign..7 in values[0]
00156     {
00157       // Create bit mask for bit positions rxAlign..7
00158       uint8_t mask = 0;
00159       for (uint8_t i = rxAlign; i <= 7; i++)
00160       {
00161         mask |= (1 << i);
00162       }
00163 
00164       // Read value and tell that we want to read the same address again.
00165       uint8_t value = m_SPI.write(address);
00166 
00167       // Apply mask to both current value of values[0] and the new data in value.
00168       values[0] = (values[index] & ~mask) | (value & mask);
00169     }
00170     else
00171     {
00172       // Read value and tell that we want to read the same address again.
00173       values[index] = m_SPI.write(address);
00174     }
00175 
00176     index++;
00177   }
00178 
00179   values[index] = m_SPI.write(0); // Read the final byte. Send 0 to stop reading.
00180 
00181   m_CS = 1;                       /* Release SPI Chip MFRC522 */
00182 } // End PCD_ReadRegister()
00183 
00184 /**
00185  * Sets the bits given in mask in register reg.
00186  */
00187 void MFRC522::PCD_SetRegisterBits(uint8_t reg, uint8_t mask)
00188 {
00189   uint8_t tmp = PCD_ReadRegister(reg);
00190   PCD_WriteRegister(reg, tmp | mask);     // set bit mask
00191 } // End PCD_SetRegisterBitMask()
00192 
00193 /**
00194  * Clears the bits given in mask from register reg.
00195  */
00196 void MFRC522::PCD_ClrRegisterBits(uint8_t reg, uint8_t mask)
00197 {
00198   uint8_t tmp = PCD_ReadRegister(reg);
00199   PCD_WriteRegister(reg, tmp & (~mask));    // clear bit mask
00200 } // End PCD_ClearRegisterBitMask()
00201 
00202 
00203 /**
00204  * Use the CRC coprocessor in the MFRC522 to calculate a CRC_A.
00205  */
00206 uint8_t MFRC522::PCD_CalculateCRC(uint8_t *data, uint8_t length, uint8_t *result)
00207 {
00208   PCD_WriteRegister(CommandReg, PCD_Idle);      // Stop any active command.
00209   PCD_WriteRegister(DivIrqReg, 0x04);           // Clear the CRCIRq interrupt request bit
00210   PCD_SetRegisterBits(FIFOLevelReg, 0x80);      // FlushBuffer = 1, FIFO initialization
00211   PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO
00212   PCD_WriteRegister(CommandReg, PCD_CalcCRC);   // Start the calculation
00213 
00214   // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us.
00215   uint16_t i = 5000;
00216   uint8_t n;
00217   while (1)
00218   {
00219     n = PCD_ReadRegister(DivIrqReg);  // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq   reserved CRCIRq reserved reserved
00220     if (n & 0x04)
00221     {
00222       // CRCIRq bit set - calculation done
00223       break;
00224     }
00225     
00226     if (--i == 0)
00227     {
00228       // The emergency break. We will eventually terminate on this one after 89ms.
00229       // Communication with the MFRC522 might be down.
00230       return STATUS_TIMEOUT;
00231     }
00232   }
00233 
00234   // Stop calculating CRC for new content in the FIFO.
00235   PCD_WriteRegister(CommandReg, PCD_Idle);
00236 
00237   // Transfer the result from the registers to the result buffer
00238   result[0] = PCD_ReadRegister(CRCResultRegL);
00239   result[1] = PCD_ReadRegister(CRCResultRegH);
00240   return STATUS_OK;
00241 } // End PCD_CalculateCRC()
00242 
00243 
00244 /////////////////////////////////////////////////////////////////////////////////////
00245 // Functions for manipulating the MFRC522
00246 /////////////////////////////////////////////////////////////////////////////////////
00247 
00248 /**
00249  * Initializes the MFRC522 chip.
00250  */
00251 void MFRC522::PCD_Init()
00252 {
00253   /* Reset MFRC522 */
00254   m_RESET = 0;
00255   wait_ms(10);
00256   m_RESET = 1;
00257   
00258   // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74us. Let us be generous: 50ms.
00259   wait_ms(50);
00260 
00261   // When communicating with a PICC we need a timeout if something goes wrong.
00262   // f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
00263   // TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
00264   PCD_WriteRegister(TModeReg, 0x80);      // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
00265   PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25us.
00266   PCD_WriteRegister(TReloadRegH, 0x03);   // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
00267   PCD_WriteRegister(TReloadRegL, 0xE8);
00268 
00269   PCD_WriteRegister(TxASKReg, 0x40);      // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
00270   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)
00271 
00272   PCD_WriteRegister(RFCfgReg, (0x07<<4)); // Set Rx Gain to max
00273 
00274   PCD_AntennaOn();                        // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
00275 } // End PCD_Init()
00276 
00277 /**
00278  * Performs a soft reset on the MFRC522 chip and waits for it to be ready again.
00279  */
00280 void MFRC522::PCD_Reset()
00281 {
00282   PCD_WriteRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
00283   // The datasheet does not mention how long the SoftRest command takes to complete.
00284   // But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
00285   // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74us. Let us be generous: 50ms.
00286   wait_ms(50);
00287 
00288   // Wait for the PowerDown bit in CommandReg to be cleared
00289   while (PCD_ReadRegister(CommandReg) & (1<<4))
00290   {
00291     // PCD still restarting - unlikely after waiting 50ms, but better safe than sorry.
00292   }
00293 } // End PCD_Reset()
00294 
00295 /**
00296  * Turns the antenna on by enabling pins TX1 and TX2.
00297  * After a reset these pins disabled.
00298  */
00299 void MFRC522::PCD_AntennaOn()
00300 {
00301   uint8_t value = PCD_ReadRegister(TxControlReg);
00302   if ((value & 0x03) != 0x03)
00303   {
00304     PCD_WriteRegister(TxControlReg, value | 0x03);
00305   }
00306 } // End PCD_AntennaOn()
00307 
00308 /////////////////////////////////////////////////////////////////////////////////////
00309 // Functions for communicating with PICCs
00310 /////////////////////////////////////////////////////////////////////////////////////
00311 
00312 /**
00313  * Executes the Transceive command.
00314  * CRC validation can only be done if backData and backLen are specified.
00315  */
00316 uint8_t MFRC522::PCD_TransceiveData(uint8_t *sendData,
00317                                     uint8_t sendLen,
00318                                     uint8_t *backData,
00319                                     uint8_t *backLen,
00320                                     uint8_t *validBits,
00321                                     uint8_t rxAlign,
00322                                     bool    checkCRC)
00323 {
00324   uint8_t waitIRq = 0x30;    // RxIRq and IdleIRq
00325   return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
00326 } // End PCD_TransceiveData()
00327 
00328 /**
00329  * Transfers data to the MFRC522 FIFO, executes a commend, waits for completion and transfers data back from the FIFO.
00330  * CRC validation can only be done if backData and backLen are specified.
00331  */
00332 uint8_t MFRC522::PCD_CommunicateWithPICC(uint8_t command,
00333                                          uint8_t waitIRq,
00334                                          uint8_t *sendData,
00335                                          uint8_t sendLen,
00336                                          uint8_t *backData,
00337                                          uint8_t *backLen,
00338                                          uint8_t *validBits,
00339                                          uint8_t rxAlign,
00340                                          bool    checkCRC)
00341 {
00342   uint8_t n, _validBits = 0;
00343   uint32_t i;
00344 
00345   // Prepare values for BitFramingReg
00346   uint8_t txLastBits = validBits ? *validBits : 0;
00347   uint8_t bitFraming = (rxAlign << 4) + txLastBits;   // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
00348 
00349   PCD_WriteRegister(CommandReg, PCD_Idle);            // Stop any active command.
00350   PCD_WriteRegister(ComIrqReg, 0x7F);                 // Clear all seven interrupt request bits
00351   PCD_SetRegisterBits(FIFOLevelReg, 0x80);            // FlushBuffer = 1, FIFO initialization
00352   PCD_WriteRegister(FIFODataReg, sendLen, sendData);  // Write sendData to the FIFO
00353   PCD_WriteRegister(BitFramingReg, bitFraming);       // Bit adjustments
00354   PCD_WriteRegister(CommandReg, command);             // Execute the command
00355   if (command == PCD_Transceive)
00356   {
00357     PCD_SetRegisterBits(BitFramingReg, 0x80);      // StartSend=1, transmission of data starts
00358   }
00359 
00360   // Wait for the command to complete.
00361   // In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
00362   // Each iteration of the do-while-loop takes 17.86us.
00363   i = 2000;
00364   while (1)
00365   {
00366     n = PCD_ReadRegister(ComIrqReg);  // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq   HiAlertIRq LoAlertIRq ErrIRq TimerIRq
00367     if (n & waitIRq)
00368     {          // One of the interrupts that signal success has been set.
00369       break;
00370     }
00371 
00372     if (n & 0x01)
00373     {           // Timer interrupt - nothing received in 25ms
00374       return STATUS_TIMEOUT;
00375     }
00376 
00377     if (--i == 0)
00378     {           // 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.
00379       return STATUS_TIMEOUT;
00380     }
00381   }
00382 
00383   // Stop now if any errors except collisions were detected.
00384   uint8_t errorRegValue = PCD_ReadRegister(ErrorReg); // ErrorReg[7..0] bits are: WrErr TempErr reserved BufferOvfl   CollErr CRCErr ParityErr ProtocolErr
00385   if (errorRegValue & 0x13)
00386   {  // BufferOvfl ParityErr ProtocolErr
00387     return STATUS_ERROR;
00388   }
00389 
00390   // If the caller wants data back, get it from the MFRC522.
00391   if (backData && backLen)
00392   {
00393     n = PCD_ReadRegister(FIFOLevelReg);           // Number of bytes in the FIFO
00394     if (n > *backLen)
00395     {
00396       return STATUS_NO_ROOM;
00397     }
00398 
00399     *backLen = n;                       // Number of bytes returned
00400     PCD_ReadRegister(FIFODataReg, n, backData, rxAlign);    // Get received data from FIFO
00401     _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.
00402     if (validBits)
00403     {
00404       *validBits = _validBits;
00405     }
00406   }
00407 
00408   // Tell about collisions
00409   if (errorRegValue & 0x08)
00410   { // CollErr
00411     return STATUS_COLLISION;
00412   }
00413 
00414   // Perform CRC_A validation if requested.
00415   if (backData && backLen && checkCRC)
00416   {
00417     // In this case a MIFARE Classic NAK is not OK.
00418     if ((*backLen == 1) && (_validBits == 4))
00419     {
00420       return STATUS_MIFARE_NACK;
00421     }
00422 
00423     // We need at least the CRC_A value and all 8 bits of the last byte must be received.
00424     if ((*backLen < 2) || (_validBits != 0))
00425     {
00426       return STATUS_CRC_WRONG;
00427     }
00428 
00429     // Verify CRC_A - do our own calculation and store the control in controlBuffer.
00430     uint8_t controlBuffer[2];
00431     n = PCD_CalculateCRC(&backData[0], *backLen - 2, &controlBuffer[0]);
00432     if (n != STATUS_OK)
00433     {
00434       return n;
00435     }
00436 
00437     if ((backData[*backLen - 2] != controlBuffer[0]) || (backData[*backLen - 1] != controlBuffer[1]))
00438     {
00439       return STATUS_CRC_WRONG;
00440     }
00441   }
00442 
00443   return STATUS_OK;
00444 } // End PCD_CommunicateWithPICC()
00445 
00446 /*
00447  * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
00448  * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
00449  */
00450 uint8_t MFRC522::PICC_RequestA(uint8_t *bufferATQA, uint8_t *bufferSize)
00451 {
00452   return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
00453 } // End PICC_RequestA()
00454 
00455 /**
00456  * 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.
00457  * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
00458  */
00459 uint8_t MFRC522::PICC_WakeupA(uint8_t *bufferATQA, uint8_t *bufferSize)
00460 {
00461   return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
00462 } // End PICC_WakeupA()
00463 
00464 /*
00465  * Transmits REQA or WUPA commands.
00466  * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
00467  */
00468 uint8_t MFRC522::PICC_REQA_or_WUPA(uint8_t command, uint8_t *bufferATQA, uint8_t *bufferSize)
00469 {
00470   uint8_t validBits;
00471   uint8_t status;
00472 
00473   if (bufferATQA == NULL || *bufferSize < 2)
00474   {  // The ATQA response is 2 bytes long.
00475     return STATUS_NO_ROOM;
00476   }
00477 
00478   // ValuesAfterColl=1 => Bits received after collision are cleared.
00479   PCD_ClrRegisterBits(CollReg, 0x80);
00480 
00481   // For REQA and WUPA we need the short frame format
00482   // - transmit only 7 bits of the last (and only) byte. TxLastBits = BitFramingReg[2..0]
00483   validBits = 7;
00484 
00485   status = PCD_TransceiveData(&command, 1, bufferATQA, bufferSize, &validBits);
00486   if (status != STATUS_OK)
00487   {
00488     return status;
00489   }
00490 
00491   if ((*bufferSize != 2) || (validBits != 0))
00492   {   // ATQA must be exactly 16 bits.
00493     return STATUS_ERROR;
00494   }
00495 
00496   return STATUS_OK;
00497 } // End PICC_REQA_or_WUPA()
00498 
00499 /*
00500  * Transmits SELECT/ANTICOLLISION commands to select a single PICC.
00501  */
00502 uint8_t MFRC522::PICC_Select(Uid *uid, uint8_t validBits)
00503 {
00504   bool uidComplete;
00505   bool selectDone;
00506   bool useCascadeTag;
00507   uint8_t cascadeLevel = 1;
00508   uint8_t result;
00509   uint8_t count;
00510   uint8_t index;
00511   uint8_t uidIndex;          // The first index in uid->uidByte[] that is used in the current Cascade Level.
00512   uint8_t currentLevelKnownBits;   // The number of known UID bits in the current Cascade Level.
00513   uint8_t buffer[9];         // The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
00514   uint8_t bufferUsed;        // The number of bytes used in the buffer, ie the number of bytes to transfer to the FIFO.
00515   uint8_t rxAlign;           // Used in BitFramingReg. Defines the bit position for the first bit received.
00516   uint8_t txLastBits;        // Used in BitFramingReg. The number of valid bits in the last transmitted byte.
00517   uint8_t *responseBuffer;
00518   uint8_t responseLength;
00519 
00520   // Description of buffer structure:
00521   //    Byte 0: SEL         Indicates the Cascade Level: PICC_CMD_SEL_CL1, PICC_CMD_SEL_CL2 or PICC_CMD_SEL_CL3
00522   //    Byte 1: NVB         Number of Valid Bits (in complete command, not just the UID): High nibble: complete bytes, Low nibble: Extra bits.
00523   //    Byte 2: UID-data or CT    See explanation below. CT means Cascade Tag.
00524   //    Byte 3: UID-data
00525   //    Byte 4: UID-data
00526   //    Byte 5: UID-data
00527   //    Byte 6: BCC         Block Check Character - XOR of bytes 2-5
00528   //    Byte 7: CRC_A
00529   //    Byte 8: CRC_A
00530   // The BCC and CRC_A is only transmitted if we know all the UID bits of the current Cascade Level.
00531   //
00532   // Description of bytes 2-5: (Section 6.5.4 of the ISO/IEC 14443-3 draft: UID contents and cascade levels)
00533   //    UID size  Cascade level Byte2 Byte3 Byte4 Byte5
00534   //    ========  ============= ===== ===== ===== =====
00535   //     4 bytes    1     uid0  uid1  uid2  uid3
00536   //     7 bytes    1     CT    uid0  uid1  uid2
00537   //                2     uid3  uid4  uid5  uid6
00538   //    10 bytes    1     CT    uid0  uid1  uid2
00539   //                2     CT    uid3  uid4  uid5
00540   //                3     uid6  uid7  uid8  uid9
00541 
00542   // Sanity checks
00543   if (validBits > 80)
00544   {
00545     return STATUS_INVALID;
00546   }
00547 
00548   // Prepare MFRC522
00549   // ValuesAfterColl=1 => Bits received after collision are cleared.
00550   PCD_ClrRegisterBits(CollReg, 0x80);
00551 
00552   // Repeat Cascade Level loop until we have a complete UID.
00553   uidComplete = false;
00554   while ( ! uidComplete)
00555   {
00556     // Set the Cascade Level in the SEL byte, find out if we need to use the Cascade Tag in byte 2.
00557     switch (cascadeLevel)
00558     {
00559       case 1:
00560         buffer[0] = PICC_CMD_SEL_CL1;
00561         uidIndex = 0;
00562         useCascadeTag = validBits && (uid->size > 4); // When we know that the UID has more than 4 bytes
00563         break;
00564 
00565       case 2:
00566         buffer[0] = PICC_CMD_SEL_CL2;
00567         uidIndex = 3;
00568         useCascadeTag = validBits && (uid->size > 7); // When we know that the UID has more than 7 bytes
00569         break;
00570 
00571       case 3:
00572         buffer[0] = PICC_CMD_SEL_CL3;
00573         uidIndex = 6;
00574         useCascadeTag = false;            // Never used in CL3.
00575         break;
00576 
00577       default:
00578         return STATUS_INTERNAL_ERROR;
00579         //break;
00580     }
00581 
00582     // How many UID bits are known in this Cascade Level?
00583     if(validBits > (8 * uidIndex))
00584     {
00585       currentLevelKnownBits = validBits - (8 * uidIndex);
00586     }
00587     else
00588     {
00589       currentLevelKnownBits = 0;
00590     }
00591 
00592     // Copy the known bits from uid->uidByte[] to buffer[]
00593     index = 2; // destination index in buffer[]
00594     if (useCascadeTag)
00595     {
00596       buffer[index++] = PICC_CMD_CT;
00597     }
00598 
00599     uint8_t bytesToCopy = currentLevelKnownBits / 8 + (currentLevelKnownBits % 8 ? 1 : 0); // The number of bytes needed to represent the known bits for this level.
00600     if (bytesToCopy)
00601     {
00602       // Max 4 bytes in each Cascade Level. Only 3 left if we use the Cascade Tag
00603       uint8_t maxBytes = useCascadeTag ? 3 : 4;
00604       if (bytesToCopy > maxBytes)
00605       {
00606         bytesToCopy = maxBytes;
00607       }
00608 
00609       for (count = 0; count < bytesToCopy; count++)
00610       {
00611         buffer[index++] = uid->uidByte[uidIndex + count];
00612       }
00613     }
00614 
00615     // Now that the data has been copied we need to include the 8 bits in CT in currentLevelKnownBits
00616     if (useCascadeTag)
00617     {
00618       currentLevelKnownBits += 8;
00619     }
00620 
00621     // Repeat anti collision loop until we can transmit all UID bits + BCC and receive a SAK - max 32 iterations.
00622     selectDone = false;
00623     while ( ! selectDone)
00624     {
00625       // Find out how many bits and bytes to send and receive.
00626       if (currentLevelKnownBits >= 32)
00627       { // All UID bits in this Cascade Level are known. This is a SELECT.
00628         //Serial.print("SELECT: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
00629         buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes
00630 
00631         // Calulate BCC - Block Check Character
00632         buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5];
00633 
00634         // Calculate CRC_A
00635         result = PCD_CalculateCRC(buffer, 7, &buffer[7]);
00636         if (result != STATUS_OK)
00637         {
00638           return result;
00639         }
00640 
00641         txLastBits      = 0; // 0 => All 8 bits are valid.
00642         bufferUsed      = 9;
00643 
00644         // Store response in the last 3 bytes of buffer (BCC and CRC_A - not needed after tx)
00645         responseBuffer  = &buffer[6];
00646         responseLength  = 3;
00647       }
00648       else
00649       { // This is an ANTICOLLISION.
00650         //Serial.print("ANTICOLLISION: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
00651         txLastBits     = currentLevelKnownBits % 8;
00652         count          = currentLevelKnownBits / 8;  // Number of whole bytes in the UID part.
00653         index          = 2 + count;                  // Number of whole bytes: SEL + NVB + UIDs
00654         buffer[1]      = (index << 4) + txLastBits;  // NVB - Number of Valid Bits
00655         bufferUsed     = index + (txLastBits ? 1 : 0);
00656 
00657         // Store response in the unused part of buffer
00658         responseBuffer = &buffer[index];
00659         responseLength = sizeof(buffer) - index;
00660       }
00661 
00662       // Set bit adjustments
00663       rxAlign = txLastBits;                     // Having a seperate variable is overkill. But it makes the next line easier to read.
00664       PCD_WriteRegister(BitFramingReg, (rxAlign << 4) + txLastBits);  // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
00665 
00666       // Transmit the buffer and receive the response.
00667       result = PCD_TransceiveData(buffer, bufferUsed, responseBuffer, &responseLength, &txLastBits, rxAlign);
00668       if (result == STATUS_COLLISION)
00669       { // More than one PICC in the field => collision.
00670         result = PCD_ReadRegister(CollReg);     // CollReg[7..0] bits are: ValuesAfterColl reserved CollPosNotValid CollPos[4:0]
00671         if (result & 0x20)
00672         { // CollPosNotValid
00673           return STATUS_COLLISION; // Without a valid collision position we cannot continue
00674         }
00675 
00676         uint8_t collisionPos = result & 0x1F; // Values 0-31, 0 means bit 32.
00677         if (collisionPos == 0)
00678         {
00679           collisionPos = 32;
00680         }
00681 
00682         if (collisionPos <= currentLevelKnownBits)
00683         { // No progress - should not happen
00684           return STATUS_INTERNAL_ERROR;
00685         }
00686 
00687         // Choose the PICC with the bit set.
00688         currentLevelKnownBits = collisionPos;
00689         count          = (currentLevelKnownBits - 1) % 8; // The bit to modify
00690         index          = 1 + (currentLevelKnownBits / 8) + (count ? 1 : 0); // First byte is index 0.
00691         buffer[index] |= (1 << count);
00692       }
00693       else if (result != STATUS_OK)
00694       {
00695         return result;
00696       }
00697       else
00698       { // STATUS_OK
00699         if (currentLevelKnownBits >= 32)
00700         { // This was a SELECT.
00701           selectDone = true; // No more anticollision
00702           // We continue below outside the while.
00703         }
00704         else
00705         { // This was an ANTICOLLISION.
00706           // We now have all 32 bits of the UID in this Cascade Level
00707           currentLevelKnownBits = 32;
00708           // Run loop again to do the SELECT.
00709         }
00710       }
00711     } // End of while ( ! selectDone)
00712 
00713     // We do not check the CBB - it was constructed by us above.
00714 
00715     // Copy the found UID bytes from buffer[] to uid->uidByte[]
00716     index       = (buffer[2] == PICC_CMD_CT) ? 3 : 2; // source index in buffer[]
00717     bytesToCopy = (buffer[2] == PICC_CMD_CT) ? 3 : 4;
00718     for (count = 0; count < bytesToCopy; count++)
00719     {
00720       uid->uidByte[uidIndex + count] = buffer[index++];
00721     }
00722 
00723     // Check response SAK (Select Acknowledge)
00724     if (responseLength != 3 || txLastBits != 0)
00725     {   // SAK must be exactly 24 bits (1 byte + CRC_A).
00726       return STATUS_ERROR;
00727     }
00728 
00729     // Verify CRC_A - do our own calculation and store the control in buffer[2..3] - those bytes are not needed anymore.
00730     result = PCD_CalculateCRC(responseBuffer, 1, &buffer[2]);
00731     if (result != STATUS_OK)
00732     {
00733       return result;
00734     }
00735 
00736     if ((buffer[2] != responseBuffer[1]) || (buffer[3] != responseBuffer[2]))
00737     {
00738       return STATUS_CRC_WRONG;
00739     }
00740 
00741     if (responseBuffer[0] & 0x04)
00742     { // Cascade bit set - UID not complete yes
00743       cascadeLevel++;
00744     }
00745     else
00746     {
00747       uidComplete = true;
00748       uid->sak = responseBuffer[0];
00749     }
00750   } // End of while ( ! uidComplete)
00751 
00752   // Set correct uid->size
00753   uid->size = 3 * cascadeLevel + 1;
00754 
00755   return STATUS_OK;
00756 } // End PICC_Select()
00757 
00758 /*
00759  * Instructs a PICC in state ACTIVE(*) to go to state HALT.
00760  */
00761 uint8_t MFRC522::PICC_HaltA()
00762 {
00763   uint8_t result;
00764   uint8_t buffer[4];
00765 
00766   // Build command buffer
00767   buffer[0] = PICC_CMD_HLTA;
00768   buffer[1] = 0;
00769 
00770   // Calculate CRC_A
00771   result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
00772   if (result == STATUS_OK)
00773   {
00774     // Send the command.
00775     // The standard says:
00776     //    If the PICC responds with any modulation during a period of 1 ms after the end of the frame containing the
00777     //    HLTA command, this response shall be interpreted as 'not acknowledge'.
00778     // We interpret that this way: Only STATUS_TIMEOUT is an success.
00779     result = PCD_TransceiveData(buffer, sizeof(buffer), NULL, 0);
00780     if (result == STATUS_TIMEOUT)
00781     {
00782       result = STATUS_OK;
00783     }
00784     else if (result == STATUS_OK)
00785     { // That is ironically NOT ok in this case ;-)
00786       result = STATUS_ERROR;
00787     }
00788   }
00789 
00790   return result;
00791 } // End PICC_HaltA()
00792 
00793 
00794 /////////////////////////////////////////////////////////////////////////////////////
00795 // Functions for communicating with MIFARE PICCs
00796 /////////////////////////////////////////////////////////////////////////////////////
00797 
00798 /*
00799  * Executes the MFRC522 MFAuthent command.
00800  */
00801 uint8_t MFRC522::PCD_Authenticate(uint8_t command, uint8_t blockAddr, MIFARE_Key *key, Uid *uid)
00802 {
00803   uint8_t i, waitIRq = 0x10;    // IdleIRq
00804 
00805   // Build command buffer
00806   uint8_t sendData[12];
00807   sendData[0] = command;
00808   sendData[1] = blockAddr;
00809 
00810   for (i = 0; i < MF_KEY_SIZE; i++)
00811   {  // 6 key bytes
00812     sendData[2+i] = key->keyByte[i];
00813   }
00814 
00815   for (i = 0; i < 4; i++)
00816   { // The first 4 bytes of the UID
00817     sendData[8+i] = uid->uidByte[i];
00818   }
00819 
00820   // Start the authentication.
00821   return PCD_CommunicateWithPICC(PCD_MFAuthent, waitIRq, &sendData[0], sizeof(sendData));
00822 } // End PCD_Authenticate()
00823 
00824 /*
00825  * Used to exit the PCD from its authenticated state.
00826  * Remember to call this function after communicating with an authenticated PICC - otherwise no new communications can start.
00827  */
00828 void MFRC522::PCD_StopCrypto1()
00829 {
00830   // Clear MFCrypto1On bit
00831   PCD_ClrRegisterBits(Status2Reg, 0x08); // Status2Reg[7..0] bits are: TempSensClear I2CForceHS reserved reserved   MFCrypto1On ModemState[2:0]
00832 } // End PCD_StopCrypto1()
00833 
00834 /*
00835  * Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.
00836  */
00837 uint8_t MFRC522::MIFARE_Read(uint8_t blockAddr, uint8_t *buffer, uint8_t *bufferSize)
00838 {
00839   uint8_t result = STATUS_NO_ROOM;
00840 
00841   // Sanity check
00842   if ((buffer == NULL) || (*bufferSize < 18))
00843   {
00844     return result;
00845   }
00846 
00847   // Build command buffer
00848   buffer[0] = PICC_CMD_MF_READ;
00849   buffer[1] = blockAddr;
00850 
00851   // Calculate CRC_A
00852   result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
00853   if (result != STATUS_OK)
00854   {
00855     return result;
00856   }
00857 
00858   // Transmit the buffer and receive the response, validate CRC_A.
00859   return PCD_TransceiveData(buffer, 4, buffer, bufferSize, NULL, 0, true);
00860 } // End MIFARE_Read()
00861 
00862 /*
00863  * Writes 16 bytes to the active PICC.
00864  */
00865 uint8_t MFRC522::MIFARE_Write(uint8_t blockAddr, uint8_t *buffer, uint8_t bufferSize)
00866 {
00867   uint8_t result;
00868 
00869   // Sanity check
00870   if (buffer == NULL || bufferSize < 16)
00871   {
00872     return STATUS_INVALID;
00873   }
00874 
00875   // Mifare Classic protocol requires two communications to perform a write.
00876   // Step 1: Tell the PICC we want to write to block blockAddr.
00877   uint8_t cmdBuffer[2];
00878   cmdBuffer[0] = PICC_CMD_MF_WRITE;
00879   cmdBuffer[1] = blockAddr;
00880   // Adds CRC_A and checks that the response is MF_ACK.
00881   result = PCD_MIFARE_Transceive(cmdBuffer, 2);
00882   if (result != STATUS_OK)
00883   {
00884     return result;
00885   }
00886 
00887   // Step 2: Transfer the data
00888   // Adds CRC_A and checks that the response is MF_ACK.
00889   result = PCD_MIFARE_Transceive(buffer, bufferSize);
00890   if (result != STATUS_OK)
00891   {
00892     return result;
00893   }
00894 
00895   return STATUS_OK;
00896 } // End MIFARE_Write()
00897 
00898 /*
00899  * Writes a 4 byte page to the active MIFARE Ultralight PICC.
00900  */
00901 uint8_t MFRC522::MIFARE_UltralightWrite(uint8_t page, uint8_t *buffer, uint8_t bufferSize)
00902 {
00903   uint8_t result;
00904 
00905   // Sanity check
00906   if (buffer == NULL || bufferSize < 4)
00907   {
00908     return STATUS_INVALID;
00909   }
00910 
00911   // Build commmand buffer
00912   uint8_t cmdBuffer[6];
00913   cmdBuffer[0] = PICC_CMD_UL_WRITE;
00914   cmdBuffer[1] = page;
00915   memcpy(&cmdBuffer[2], buffer, 4);
00916 
00917   // Perform the write
00918   result = PCD_MIFARE_Transceive(cmdBuffer, 6); // Adds CRC_A and checks that the response is MF_ACK.
00919   if (result != STATUS_OK)
00920   {
00921     return result;
00922   }
00923 
00924   return STATUS_OK;
00925 } // End MIFARE_Ultralight_Write()
00926 
00927 /*
00928  * MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
00929  */
00930 uint8_t MFRC522::MIFARE_Decrement(uint8_t blockAddr, uint32_t delta)
00931 {
00932   return MIFARE_TwoStepHelper(PICC_CMD_MF_DECREMENT, blockAddr, delta);
00933 } // End MIFARE_Decrement()
00934 
00935 /*
00936  * MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
00937  */
00938 uint8_t MFRC522::MIFARE_Increment(uint8_t blockAddr, uint32_t delta)
00939 {
00940   return MIFARE_TwoStepHelper(PICC_CMD_MF_INCREMENT, blockAddr, delta);
00941 } // End MIFARE_Increment()
00942 
00943 /**
00944  * MIFARE Restore copies the value of the addressed block into a volatile memory.
00945  */
00946 uint8_t MFRC522::MIFARE_Restore(uint8_t blockAddr)
00947 {
00948   // The datasheet describes Restore as a two step operation, but does not explain what data to transfer in step 2.
00949   // Doing only a single step does not work, so I chose to transfer 0L in step two.
00950   return MIFARE_TwoStepHelper(PICC_CMD_MF_RESTORE, blockAddr, 0L);
00951 } // End MIFARE_Restore()
00952 
00953 /*
00954  * Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
00955  */
00956 uint8_t MFRC522::MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, uint32_t data)
00957 {
00958   uint8_t result;
00959   uint8_t cmdBuffer[2]; // We only need room for 2 bytes.
00960 
00961   // Step 1: Tell the PICC the command and block address
00962   cmdBuffer[0] = command;
00963   cmdBuffer[1] = blockAddr;
00964 
00965   // Adds CRC_A and checks that the response is MF_ACK.
00966   result = PCD_MIFARE_Transceive(cmdBuffer, 2);
00967   if (result != STATUS_OK)
00968   {
00969     return result;
00970   }
00971 
00972   // Step 2: Transfer the data
00973   // Adds CRC_A and accept timeout as success.
00974   result = PCD_MIFARE_Transceive((uint8_t *) &data, 4, true);
00975   if (result != STATUS_OK)
00976   {
00977     return result;
00978   }
00979 
00980   return STATUS_OK;
00981 } // End MIFARE_TwoStepHelper()
00982 
00983 /*
00984  * MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
00985  */
00986 uint8_t MFRC522::MIFARE_Transfer(uint8_t blockAddr)
00987 {
00988   uint8_t cmdBuffer[2]; // We only need room for 2 bytes.
00989 
00990   // Tell the PICC we want to transfer the result into block blockAddr.
00991   cmdBuffer[0] = PICC_CMD_MF_TRANSFER;
00992   cmdBuffer[1] = blockAddr;
00993 
00994   // Adds CRC_A and checks that the response is MF_ACK.
00995   return PCD_MIFARE_Transceive(cmdBuffer, 2);
00996 } // End MIFARE_Transfer()
00997 
00998 
00999 /////////////////////////////////////////////////////////////////////////////////////
01000 // Support functions
01001 /////////////////////////////////////////////////////////////////////////////////////
01002 
01003 /*
01004  * Wrapper for MIFARE protocol communication.
01005  * Adds CRC_A, executes the Transceive command and checks that the response is MF_ACK or a timeout.
01006  */
01007 uint8_t MFRC522::PCD_MIFARE_Transceive(uint8_t *sendData, uint8_t sendLen, bool acceptTimeout)
01008 {
01009   uint8_t result;
01010   uint8_t cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A.
01011 
01012   // Sanity check
01013   if (sendData == NULL || sendLen > 16)
01014   {
01015     return STATUS_INVALID;
01016   }
01017 
01018   // Copy sendData[] to cmdBuffer[] and add CRC_A
01019   memcpy(cmdBuffer, sendData, sendLen);
01020   result = PCD_CalculateCRC(cmdBuffer, sendLen, &cmdBuffer[sendLen]);
01021   if (result != STATUS_OK)
01022   {
01023     return result;
01024   }
01025 
01026   sendLen += 2;
01027 
01028   // Transceive the data, store the reply in cmdBuffer[]
01029   uint8_t waitIRq = 0x30;    // RxIRq and IdleIRq
01030   uint8_t cmdBufferSize = sizeof(cmdBuffer);
01031   uint8_t validBits = 0;
01032   result = PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, cmdBuffer, sendLen, cmdBuffer, &cmdBufferSize, &validBits);
01033   if (acceptTimeout && result == STATUS_TIMEOUT)
01034   {
01035     return STATUS_OK;
01036   }
01037 
01038   if (result != STATUS_OK)
01039   {
01040     return result;
01041   }
01042 
01043   // The PICC must reply with a 4 bit ACK
01044   if (cmdBufferSize != 1 || validBits != 4)
01045   {
01046     return STATUS_ERROR;
01047   }
01048 
01049   if (cmdBuffer[0] != MF_ACK)
01050   {
01051     return STATUS_MIFARE_NACK;
01052   }
01053 
01054   return STATUS_OK;
01055 } // End PCD_MIFARE_Transceive()
01056 
01057 
01058 /*
01059  * Translates the SAK (Select Acknowledge) to a PICC type.
01060  */
01061 uint8_t MFRC522::PICC_GetType(uint8_t sak)
01062 {
01063   uint8_t retType = PICC_TYPE_UNKNOWN;
01064 
01065   if (sak & 0x04)
01066   { // UID not complete
01067     retType = PICC_TYPE_NOT_COMPLETE;
01068   }
01069   else
01070   {
01071     switch (sak)
01072     {
01073       case 0x09: retType = PICC_TYPE_MIFARE_MINI; break;
01074       case 0x08: retType = PICC_TYPE_MIFARE_1K;   break;
01075       case 0x18: retType = PICC_TYPE_MIFARE_4K;   break;
01076       case 0x00: retType = PICC_TYPE_MIFARE_UL;   break;
01077       case 0x10:
01078       case 0x11: retType = PICC_TYPE_MIFARE_PLUS; break;
01079       case 0x01: retType = PICC_TYPE_TNP3XXX;     break;
01080       default:
01081         if (sak & 0x20)
01082         {
01083           retType = PICC_TYPE_ISO_14443_4;
01084         }
01085         else if (sak & 0x40)
01086         {
01087           retType = PICC_TYPE_ISO_18092;
01088         }
01089         break;
01090     }
01091   }
01092 
01093   return (retType);
01094 } // End PICC_GetType()
01095 
01096 /*
01097  * Returns a string pointer to the PICC type name.
01098  */
01099 char* MFRC522::PICC_GetTypeName(uint8_t piccType)
01100 {
01101   if(piccType == PICC_TYPE_NOT_COMPLETE)
01102   {
01103     piccType = MFRC522_MaxPICCs - 1;
01104   }
01105 
01106   return((char *) _TypeNamePICC[piccType]);
01107 } // End PICC_GetTypeName()
01108 
01109 /*
01110  * Returns a string pointer to a status code name.
01111  */
01112 char* MFRC522::GetStatusCodeName(uint8_t code)
01113 {
01114   return((char *) _ErrorMessage[code]);
01115 } // End GetStatusCodeName()
01116 
01117 /*
01118  * 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).
01119  */
01120 void MFRC522::MIFARE_SetAccessBits(uint8_t *accessBitBuffer,  
01121                                    uint8_t g0,                
01122                                    uint8_t g1,                
01123                                    uint8_t g2,                
01124                                    uint8_t g3)
01125 {
01126   uint8_t c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2);
01127   uint8_t c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1);
01128   uint8_t c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0);
01129 
01130   accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF);
01131   accessBitBuffer[1] =          c1 << 4 | (~c3 & 0xF);
01132   accessBitBuffer[2] =          c3 << 4 | c2;
01133 } // End MIFARE_SetAccessBits()
01134 
01135 /////////////////////////////////////////////////////////////////////////////////////
01136 // Convenience functions - does not add extra functionality
01137 /////////////////////////////////////////////////////////////////////////////////////
01138 
01139 /*
01140  * Returns true if a PICC responds to PICC_CMD_REQA.
01141  * Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.
01142  */
01143 bool MFRC522::PICC_IsNewCardPresent(void)
01144 {
01145   uint8_t bufferATQA[2];
01146   uint8_t bufferSize = sizeof(bufferATQA);
01147   uint8_t result = PICC_RequestA(bufferATQA, &bufferSize);
01148   return ((result == STATUS_OK) || (result == STATUS_COLLISION));
01149 } // End PICC_IsNewCardPresent()
01150 
01151 /*
01152  * Simple wrapper around PICC_Select.
01153  */
01154 bool MFRC522::PICC_ReadCardSerial(void)
01155 {
01156   uint8_t result = PICC_Select(&uid);
01157   return (result == STATUS_OK);
01158 } // End PICC_ReadCardSerial()