Andrea Corrado / Mbed OS RFID-RC522

Fork of RFID-RC522 by Thomas Kirchner

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