test ok
Dependents: DR14_FRDM_MFRC522 RFID-RC522_LCD_16x2_A1602
Fork of MFRC522 by
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 01115 01116 01117 /* 01118 * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tupples C1 is MSB (=4) and C3 is LSB (=1). 01119 */ 01120 void MFRC522::MIFARE_SetAccessBits(uint8_t *accessBitBuffer, 01121 uint8_t g0, 01122 uint8_t g1, 01123 uint8_t g2, 01124 uint8_t g3) 01125 { 01126 uint8_t c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2); 01127 uint8_t c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1); 01128 uint8_t c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0); 01129 01130 accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF); 01131 accessBitBuffer[1] = c1 << 4 | (~c3 & 0xF); 01132 accessBitBuffer[2] = c3 << 4 | c2; 01133 } // End MIFARE_SetAccessBits() 01134 01135 ///////////////////////////////////////////////////////////////////////////////////// 01136 // Convenience functions - does not add extra functionality 01137 ///////////////////////////////////////////////////////////////////////////////////// 01138 01139 /* 01140 * Returns true if a PICC responds to PICC_CMD_REQA. 01141 * Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored. 01142 */ 01143 bool MFRC522::PICC_IsNewCardPresent(void) 01144 { 01145 uint8_t bufferATQA[2]; 01146 uint8_t bufferSize = sizeof(bufferATQA); 01147 uint8_t result = PICC_RequestA(bufferATQA, &bufferSize); 01148 return ((result == STATUS_OK) || (result == STATUS_COLLISION)); 01149 } // End PICC_IsNewCardPresent() 01150 01151 /* 01152 * Simple wrapper around PICC_Select. 01153 */ 01154 bool MFRC522::PICC_ReadCardSerial(void) 01155 { 01156 uint8_t result = PICC_Select(&uid); 01157 return (result == STATUS_OK); 01158 } // End PICC_ReadCardSerial()
Generated on Sat Jul 16 2022 21:38:08 by
