RFID-RC522 code for testing a cheap 13.56 MHz module with the Nucleo F401RE. Based on the MFRC522 code by Martin Olejar.

Dependencies:   mbed

Dependents:   RFID-RC522

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