Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MFRC522 by
Revision 1:63d729186747, committed 2014-01-06
- Comitter:
- AtomX
- Date:
- Mon Jan 06 15:00:15 2014 +0000
- Parent:
- 0:efd786b99a72
- Child:
- 2:a0c7513fb634
- Commit message:
- updated coments
Changed in this revision
| MFRC522.cpp | Show annotated file Show diff for this revision Revisions of this file |
| MFRC522.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/MFRC522.cpp Wed Dec 18 00:39:55 2013 +0000
+++ b/MFRC522.cpp Mon Jan 06 15:00:15 2014 +0000
@@ -202,12 +202,12 @@
uint8_t MFRC522::PCD_CalculateCRC(uint8_t *data, uint8_t length, uint8_t *result)
{
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
- PCD_WriteRegister(DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit
- PCD_SetRegisterBits(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
- PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO
+ PCD_WriteRegister(DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit
+ PCD_SetRegisterBits(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
+ PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO
PCD_WriteRegister(CommandReg, PCD_CalcCRC); // Start the calculation
- // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73�s.
+ // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us.
uint16_t i = 5000;
uint8_t n;
while (1)
@@ -218,6 +218,7 @@
// CRCIRq bit set - calculation done
break;
}
+
if (--i == 0)
{
// The emergency break. We will eventually terminate on this one after 89ms.
@@ -249,14 +250,15 @@
m_RESET = 0;
wait_ms(10);
m_RESET = 1;
- // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74�s. Let us be generous: 50ms.
+
+ // 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.
wait_ms(50);
// When communicating with a PICC we need a timeout if something goes wrong.
// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
PCD_WriteRegister(TModeReg, 0x80); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
- PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25�s.
+ PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25us.
PCD_WriteRegister(TReloadRegH, 0x03); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
PCD_WriteRegister(TReloadRegL, 0xE8);
@@ -276,7 +278,7 @@
PCD_WriteRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
// The datasheet does not mention how long the SoftRest command takes to complete.
// But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
- // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74�s. Let us be generous: 50ms.
+ // 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.
wait_ms(50);
// Wait for the PowerDown bit in CommandReg to be cleared
@@ -306,16 +308,14 @@
/**
* Executes the Transceive command.
* CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
-uint8_t MFRC522::PCD_TransceiveData(uint8_t *sendData, ///< Pointer to the data to transfer to the FIFO.
- uint8_t sendLen, ///< Number of bytes to transfer to the FIFO.
- uint8_t *backData, ///< NULL or pointer to buffer if data should be read back after executing the command.
- uint8_t *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
- uint8_t *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default NULL.
- uint8_t rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
- bool checkCRC) ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
+uint8_t MFRC522::PCD_TransceiveData(uint8_t *sendData,
+ uint8_t sendLen,
+ uint8_t *backData,
+ uint8_t *backLen,
+ uint8_t *validBits,
+ uint8_t rxAlign,
+ bool checkCRC)
{
uint8_t waitIRq = 0x30; // RxIRq and IdleIRq
return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
@@ -324,18 +324,16 @@
/**
* Transfers data to the MFRC522 FIFO, executes a commend, waits for completion and transfers data back from the FIFO.
* CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
-uint8_t MFRC522::PCD_CommunicateWithPICC(uint8_t command, ///< The command to execute. One of the PCD_Command enums.
- uint8_t waitIRq, ///< The bits in the ComIrqReg register that signals successful completion of the command.
- uint8_t *sendData, ///< Pointer to the data to transfer to the FIFO.
- uint8_t sendLen, ///< Number of bytes to transfer to the FIFO.
- uint8_t *backData, ///< NULL or pointer to buffer if data should be read back after executing the command.
- uint8_t *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
- uint8_t *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
- uint8_t rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
- bool checkCRC) ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
+uint8_t MFRC522::PCD_CommunicateWithPICC(uint8_t command,
+ uint8_t waitIRq,
+ uint8_t *sendData,
+ uint8_t sendLen,
+ uint8_t *backData,
+ uint8_t *backLen,
+ uint8_t *validBits,
+ uint8_t rxAlign,
+ bool checkCRC)
{
uint8_t n, _validBits = 0;
uint32_t i;
@@ -357,7 +355,7 @@
// Wait for the command to complete.
// In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
- // Each iteration of the do-while-loop takes 17.86�s.
+ // Each iteration of the do-while-loop takes 17.86us.
i = 2000;
while (1)
{
@@ -441,11 +439,9 @@
return STATUS_OK;
} // End PCD_CommunicateWithPICC()
-/**
+/*
* Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
* Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PICC_RequestA(uint8_t *bufferATQA, uint8_t *bufferSize)
{
@@ -455,19 +451,15 @@
/**
* 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.
* Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PICC_WakeupA(uint8_t *bufferATQA, uint8_t *bufferSize)
{
return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
} // End PICC_WakeupA()
-/**
+/*
* Transmits REQA or WUPA commands.
* Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PICC_REQA_or_WUPA(uint8_t command, uint8_t *bufferATQA, uint8_t *bufferSize)
{
@@ -500,22 +492,8 @@
return STATUS_OK;
} // End PICC_REQA_or_WUPA()
-/**
+/*
* Transmits SELECT/ANTICOLLISION commands to select a single PICC.
- * Before calling this function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or PICC_WakeupA().
- * On success:
- * - The chosen PICC is in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)
- * - The UID size and value of the chosen PICC is returned in *uid along with the SAK.
- *
- * A PICC UID consists of 4, 7 or 10 bytes.
- * Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two or three iterations are used:
- * UID size Number of UID bytes Cascade levels Example of PICC
- * ======== =================== ============== ===============
- * single 4 1 MIFARE Classic
- * double 7 2 MIFARE Ultralight
- * triple 10 3 Not currently in use?
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PICC_Select(Uid *uid, uint8_t validBits)
{
@@ -773,10 +751,8 @@
return STATUS_OK;
} // End PICC_Select()
-/**
+/*
* Instructs a PICC in state ACTIVE(*) to go to state HALT.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PICC_HaltA()
{
@@ -815,17 +791,8 @@
// Functions for communicating with MIFARE PICCs
/////////////////////////////////////////////////////////////////////////////////////
-/**
+/*
* Executes the MFRC522 MFAuthent command.
- * This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.
- * The authentication is described in the MFRC522 datasheet section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1.
- * For use with MIFARE Classic PICCs.
- * The PICC must be selected - ie in state ACTIVE(*) - before calling this function.
- * Remember to call PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise no new communications can start.
- *
- * All keys are set to FFFFFFFFFFFFh at chip delivery.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.
*/
uint8_t MFRC522::PCD_Authenticate(uint8_t command, uint8_t blockAddr, MIFARE_Key *key, Uid *uid)
{
@@ -850,7 +817,7 @@
return PCD_CommunicateWithPICC(PCD_MFAuthent, waitIRq, &sendData[0], sizeof(sendData));
} // End PCD_Authenticate()
-/**
+/*
* Used to exit the PCD from its authenticated state.
* Remember to call this function after communicating with an authenticated PICC - otherwise no new communications can start.
*/
@@ -860,21 +827,8 @@
PCD_ClrRegisterBits(Status2Reg, 0x08); // Status2Reg[7..0] bits are: TempSensClear I2CForceHS reserved reserved MFCrypto1On ModemState[2:0]
} // End PCD_StopCrypto1()
-/**
+/*
* Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight only addresses 00h to 0Fh are decoded.
- * The MF0ICU1 returns a NAK for higher addresses.
- * The MF0ICU1 responds to the READ command by sending 16 bytes starting from the page address defined by the command argument.
- * For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned.
- * A roll-back is implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are returned.
- *
- * The buffer must be at least 18 bytes because a CRC_A is also returned.
- * Checks the CRC_A before returning STATUS_OK.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Read(uint8_t blockAddr, uint8_t *buffer, uint8_t *bufferSize)
{
@@ -901,16 +855,8 @@
return PCD_TransceiveData(buffer, 4, buffer, bufferSize, NULL, 0, true);
} // End MIFARE_Read()
-/**
+/*
* Writes 16 bytes to the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight the opretaion is called "COMPATIBILITY WRITE".
- * Even though 16 bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes 0 to 3)
- * are written to the specified address. It is recommended to set the remaining bytes 04h to 0Fh to all logic 0.
- * *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Write(uint8_t blockAddr, uint8_t *buffer, uint8_t bufferSize)
{
@@ -945,10 +891,8 @@
return STATUS_OK;
} // End MIFARE_Write()
-/**
+/*
* Writes a 4 byte page to the active MIFARE Ultralight PICC.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_UltralightWrite(uint8_t page, uint8_t *buffer, uint8_t bufferSize)
{
@@ -976,26 +920,16 @@
return STATUS_OK;
} // End MIFARE_Ultralight_Write()
-/**
+/*
* MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Decrement(uint8_t blockAddr, uint32_t delta)
{
return MIFARE_TwoStepHelper(PICC_CMD_MF_DECREMENT, blockAddr, delta);
} // End MIFARE_Decrement()
-/**
+/*
* MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Increment(uint8_t blockAddr, uint32_t delta)
{
@@ -1004,11 +938,6 @@
/**
* MIFARE Restore copies the value of the addressed block into a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Restore(uint8_t blockAddr)
{
@@ -1017,10 +946,8 @@
return MIFARE_TwoStepHelper(PICC_CMD_MF_RESTORE, blockAddr, 0L);
} // End MIFARE_Restore()
-/**
+/*
* Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, uint32_t data)
{
@@ -1049,12 +976,8 @@
return STATUS_OK;
} // End MIFARE_TwoStepHelper()
-/**
+/*
* MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::MIFARE_Transfer(uint8_t blockAddr)
{
@@ -1073,11 +996,9 @@
// Support functions
/////////////////////////////////////////////////////////////////////////////////////
-/**
+/*
* Wrapper for MIFARE protocol communication.
* Adds CRC_A, executes the Transceive command and checks that the response is MF_ACK or a timeout.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t MFRC522::PCD_MIFARE_Transceive(uint8_t *sendData, uint8_t sendLen, bool acceptTimeout)
{
@@ -1130,10 +1051,8 @@
} // End PCD_MIFARE_Transceive()
-/**
+/*
* Translates the SAK (Select Acknowledge) to a PICC type.
- *
- * @return PICC_Type
*/
uint8_t MFRC522::PICC_GetType(uint8_t sak)
{
@@ -1170,9 +1089,8 @@
return (retType);
} // End PICC_GetType()
-/**
+/*
* Returns a string pointer to the PICC type name.
- *
*/
char* MFRC522::PICC_GetTypeName(uint8_t piccType)
{
@@ -1184,23 +1102,22 @@
return((char *) _TypeNamePICC[piccType]);
} // End PICC_GetTypeName()
-/**
+/*
* Returns a string pointer to a status code name.
- *
*/
char* MFRC522::GetStatusCodeName(uint8_t code)
{
return((char *) _ErrorMessage[code]);
} // End GetStatusCodeName()
-/**
+/*
* 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).
*/
-void MFRC522::MIFARE_SetAccessBits(uint8_t *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
- uint8_t g0, ///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
- uint8_t g1, ///< Access bits C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
- uint8_t g2, ///< Access bits C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
- uint8_t g3) ///< Access bits C1 C2 C3] for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
+void MFRC522::MIFARE_SetAccessBits(uint8_t *accessBitBuffer,
+ uint8_t g0,
+ uint8_t g1,
+ uint8_t g2,
+ uint8_t g3)
{
uint8_t c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2);
uint8_t c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1);
@@ -1215,11 +1132,9 @@
// Convenience functions - does not add extra functionality
/////////////////////////////////////////////////////////////////////////////////////
-/**
+/*
* Returns true if a PICC responds to PICC_CMD_REQA.
* Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.
- *
- * @return bool
*/
bool MFRC522::PICC_IsNewCardPresent(void)
{
@@ -1229,13 +1144,8 @@
return ((result == STATUS_OK) || (result == STATUS_COLLISION));
} // End PICC_IsNewCardPresent()
-/**
+/*
* Simple wrapper around PICC_Select.
- * Returns true if a UID could be read.
- * Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() first.
- * The read UID is available in the class variable uid.
- *
- * @return bool
*/
bool MFRC522::PICC_ReadCardSerial(void)
{
--- a/MFRC522.h Wed Dec 18 00:39:55 2013 +0000
+++ b/MFRC522.h Mon Jan 06 15:00:15 2014 +0000
@@ -146,11 +146,14 @@
* }
* @endcode
*/
+
class MFRC522 {
public:
- // MFRC522 registers. Described in chapter 9 of the datasheet.
- // When using SPI all addresses are shifted one bit left in the "SPI address byte" (section 8.1.2.3)
+ /**
+ * MFRC522 registers (described in chapter 9 of the datasheet).
+ * When using SPI all addresses are shifted one bit left in the "SPI address byte" (section 8.1.2.3)
+ */
enum PCD_Register {
// Page 0: Command and status
// 0x00 // reserved for future use
@@ -333,6 +336,12 @@
* MFRC522 destructor
*/
~MFRC522();
+
+
+ // ************************************************************************************
+ //! @name Functions for manipulating the MFRC522
+ // ************************************************************************************
+ //@{
/**
* Initializes the MFRC522 chip.
@@ -426,6 +435,7 @@
* @param validBits The number of valid bits in the last byte. 0 for 8 valid bits. Default NULL.
* @param rxAlign Defines the bit position in backData[0] for the first bit received. Default 0.
* @param checkCRC True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
+ *
* @return STATUS_OK on success, STATUS_??? otherwise.
*/
uint8_t PCD_TransceiveData (uint8_t *sendData,
@@ -437,6 +447,22 @@
bool checkCRC = false);
+ /**
+ * Transfers data to the MFRC522 FIFO, executes a commend, waits for completion and transfers data back from the FIFO.
+ * CRC validation can only be done if backData and backLen are specified.
+ *
+ * @param command The command to execute. One of the PCD_Command enums.
+ * @param waitIRq The bits in the ComIrqReg register that signals successful completion of the command.
+ * @param sendData Pointer to the data to transfer to the FIFO.
+ * @param sendLen Number of bytes to transfer to the FIFO.
+ * @param backData NULL or pointer to buffer if data should be read back after executing the command.
+ * @param backLen In: Max number of bytes to write to *backData. Out: The number of bytes returned.
+ * @param validBits In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
+ * @param rxAlign In: Defines the bit position in backData[0] for the first bit received. Default 0.
+ * @param checkCRC In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PCD_CommunicateWithPICC(uint8_t command,
uint8_t waitIRq,
uint8_t *sendData,
@@ -447,47 +473,296 @@
uint8_t rxAlign = 0,
bool checkCRC = false);
-
+ /**
+ * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
+ * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
+ *
+ * @param bufferATQA The buffer to store the ATQA (Answer to request) in
+ * @param bufferSize Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PICC_RequestA (uint8_t *bufferATQA, uint8_t *bufferSize);
+
+ /**
+ * 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.
+ * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
+ *
+ * @param bufferATQA The buffer to store the ATQA (Answer to request) in
+ * @param bufferSize Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PICC_WakeupA (uint8_t *bufferATQA, uint8_t *bufferSize);
+
+ /**
+ * Transmits REQA or WUPA commands.
+ * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
+ *
+ * @param command The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
+ * @param bufferATQA The buffer to store the ATQA (Answer to request) in
+ * @param bufferSize Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PICC_REQA_or_WUPA (uint8_t command, uint8_t *bufferATQA, uint8_t *bufferSize);
+
+ /**
+ * Transmits SELECT/ANTICOLLISION commands to select a single PICC.
+ * Before calling this function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or PICC_WakeupA().
+ * On success:
+ * - The chosen PICC is in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)
+ * - The UID size and value of the chosen PICC is returned in *uid along with the SAK.
+ *
+ * A PICC UID consists of 4, 7 or 10 bytes.
+ * Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two or three iterations are used:
+ *
+ * UID size Number of UID bytes Cascade levels Example of PICC
+ * ======== =================== ============== ===============
+ * single 4 1 MIFARE Classic
+ * double 7 2 MIFARE Ultralight
+ * triple 10 3 Not currently in use?
+ *
+ *
+ * @param uid Pointer to Uid struct. Normally output, but can also be used to supply a known UID.
+ * @param validBits The number of known UID bits supplied in *uid. Normally 0. If set you must also supply uid->size.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PICC_Select (Uid *uid, uint8_t validBits = 0);
+
+ /**
+ * Instructs a PICC in state ACTIVE(*) to go to state HALT.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PICC_HaltA (void);
+
+ // ************************************************************************************
+ //@}
- /////////////////////////////////////////////////////////////////////////////////////
- // Functions for communicating with MIFARE PICCs
- /////////////////////////////////////////////////////////////////////////////////////
+ // ************************************************************************************
+ //! @name Functions for communicating with MIFARE PICCs
+ // ************************************************************************************
+ //@{
+
+ /**
+ * Executes the MFRC522 MFAuthent command.
+ * This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.
+ * The authentication is described in the MFRC522 datasheet section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1.
+ * For use with MIFARE Classic PICCs.
+ * The PICC must be selected - ie in state ACTIVE(*) - before calling this function.
+ * Remember to call PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise no new communications can start.
+ *
+ * All keys are set to FFFFFFFFFFFFh at chip delivery.
+ *
+ * @param command PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B
+ * @param blockAddr The block number. See numbering in the comments in the .h file.
+ * @param key Pointer to the Crypteo1 key to use (6 bytes)
+ * @param uid Pointer to Uid struct. The first 4 bytes of the UID is used.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.
+ */
uint8_t PCD_Authenticate (uint8_t command, uint8_t blockAddr, MIFARE_Key *key, Uid *uid);
+
+ /**
+ * Used to exit the PCD from its authenticated state.
+ * Remember to call this function after communicating with an authenticated PICC - otherwise no new communications can start.
+ */
void PCD_StopCrypto1 (void);
+
+ /**
+ * Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.
+ *
+ * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
+ *
+ * For MIFARE Ultralight only addresses 00h to 0Fh are decoded.
+ * The MF0ICU1 returns a NAK for higher addresses.
+ * The MF0ICU1 responds to the READ command by sending 16 bytes starting from the page address defined by the command argument.
+ * For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned.
+ * A roll-back is implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are returned.
+ *
+ * The buffer must be at least 18 bytes because a CRC_A is also returned.
+ * Checks the CRC_A before returning STATUS_OK.
+ *
+ * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The first page to return data from.
+ * @param buffer The buffer to store the data in
+ * @param bufferSize Buffer size, at least 18 bytes. Also number of bytes returned if STATUS_OK.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Read (uint8_t blockAddr, uint8_t *buffer, uint8_t *bufferSize);
+
+ /**
+ * Writes 16 bytes to the active PICC.
+ *
+ * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
+ *
+ * For MIFARE Ultralight the opretaion is called "COMPATIBILITY WRITE".
+ * Even though 16 bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes 0 to 3)
+ * are written to the specified address. It is recommended to set the remaining bytes 04h to 0Fh to all logic 0.
+ *
+ * @param blockAddr MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The page (2-15) to write to.
+ * @param buffer The 16 bytes to write to the PICC
+ * @param bufferSize Buffer size, must be at least 16 bytes. Exactly 16 bytes are written.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Write (uint8_t blockAddr, uint8_t *buffer, uint8_t bufferSize);
+
+ /**
+ * Writes a 4 byte page to the active MIFARE Ultralight PICC.
+ *
+ * @param page The page (2-15) to write to.
+ * @param buffer The 4 bytes to write to the PICC
+ * @param bufferSize Buffer size, must be at least 4 bytes. Exactly 4 bytes are written.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
+ uint8_t MIFARE_UltralightWrite(uint8_t page, uint8_t *buffer, uint8_t bufferSize);
+
+ /**
+ * MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
+ * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
+ * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
+ * Use MIFARE_Transfer() to store the result in a block.
+ *
+ * @param blockAddr The block (0-0xff) number.
+ * @param delta This number is subtracted from the value of block blockAddr.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Decrement (uint8_t blockAddr, uint32_t delta);
+
+ /**
+ * MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
+ * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
+ * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
+ * Use MIFARE_Transfer() to store the result in a block.
+ *
+ * @param blockAddr The block (0-0xff) number.
+ * @param delta This number is added to the value of block blockAddr.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Increment (uint8_t blockAddr, uint32_t delta);
+
+ /**
+ * MIFARE Restore copies the value of the addressed block into a volatile memory.
+ * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
+ * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
+ * Use MIFARE_Transfer() to store the result in a block.
+ *
+ * @param blockAddr The block (0-0xff) number.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Restore (uint8_t blockAddr);
+
+ /**
+ * MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
+ * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
+ * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
+ *
+ * @param blockAddr The block (0-0xff) number.
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_Transfer (uint8_t blockAddr);
- uint8_t MIFARE_UltralightWrite(uint8_t page, uint8_t *buffer, uint8_t bufferSize);
+
+ // ************************************************************************************
+ //@}
- /////////////////////////////////////////////////////////////////////////////////////
- // Support functions
- /////////////////////////////////////////////////////////////////////////////////////
+ // ************************************************************************************
+ //! @name Support functions
+ // ************************************************************************************
+ //@{
+
+ /**
+ * Wrapper for MIFARE protocol communication.
+ * Adds CRC_A, executes the Transceive command and checks that the response is MF_ACK or a timeout.
+ *
+ * @param sendData Pointer to the data to transfer to the FIFO. Do NOT include the CRC_A.
+ * @param sendLen Number of bytes in sendData.
+ * @param acceptTimeout True => A timeout is also success
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t PCD_MIFARE_Transceive(uint8_t *sendData, uint8_t sendLen, bool acceptTimeout = false);
+
+ /**
+ * Translates the SAK (Select Acknowledge) to a PICC type.
+ *
+ * @param sak The SAK byte returned from PICC_Select().
+ *
+ * @return PICC_Type
+ */
uint8_t PICC_GetType (uint8_t sak);
+
+ /**
+ * Returns a string pointer to the PICC type name.
+ *
+ * @param type One of the PICC_Type enums.
+ *
+ * @return A string pointer to the PICC type name.
+ */
char* PICC_GetTypeName (uint8_t type);
+
+ /**
+ * Returns a string pointer to a status code name.
+ *
+ * @param code One of the StatusCode enums.
+ *
+ * @return A string pointer to a status code name.
+ */
char* GetStatusCodeName (uint8_t code);
+
+ /**
+ * 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).
+ *
+ * @param accessBitBuffer Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
+ * @param g0 Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
+ * @param g1 Access bits [C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
+ * @param g2 Access bits [C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
+ * @param g3 Access bits [C1 C2 C3] for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
+ */
void MIFARE_SetAccessBits (uint8_t *accessBitBuffer,
uint8_t g0,
uint8_t g1,
uint8_t g2,
uint8_t g3);
+
+ // ************************************************************************************
+ //@}
- /////////////////////////////////////////////////////////////////////////////////////
- // Convenience functions - does not add extra functionality
- /////////////////////////////////////////////////////////////////////////////////////
+ // ************************************************************************************
+ //! @name Convenience functions - does not add extra functionality
+ // ************************************************************************************
+ //@{
+
+ /**
+ * Returns true if a PICC responds to PICC_CMD_REQA.
+ * Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.
+ *
+ * @return bool
+ */
bool PICC_IsNewCardPresent(void);
+
+ /**
+ * Simple wrapper around PICC_Select.
+ * Returns true if a UID could be read.
+ * Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() first.
+ * The read UID is available in the class variable uid.
+ *
+ * @return bool
+ */
bool PICC_ReadCardSerial (void);
+
+ // ************************************************************************************
+ //@}
private:
@@ -495,6 +770,15 @@
DigitalOut m_CS;
DigitalOut m_RESET;
+ /**
+ * Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
+ *
+ * @param command The command to use
+ * @param blockAddr The block (0-0xff) number.
+ * @param data The data to transfer in step 2
+ *
+ * @return STATUS_OK on success, STATUS_??? otherwise.
+ */
uint8_t MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, uint32_t data);
};
