Anyela Prado / MFRC522

Dependents:   ETRFID

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