From ffe097628257932504ce3ac4cbf4bb489b06e317 Mon Sep 17 00:00:00 2001 From: Rotzbua Date: Wed, 11 Mar 2015 17:30:06 +0100 Subject: [PATCH 1/3] use F() macro for return strings by functions fkt GetStatusCodeName() and PICC_GetTypeName() return pointer to flash saves about 450 byte memory if you need char: copy it from the flash --- MFRC522.cpp | 50 ++++++++++++++++++++++++-------------------------- MFRC522.h | 10 +++++++--- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/MFRC522.cpp b/MFRC522.cpp index 441f1e9..5cee248 100644 --- a/MFRC522.cpp +++ b/MFRC522.cpp @@ -1067,24 +1067,22 @@ byte MFRC522::PCD_MIFARE_Transceive( byte *sendData, ///< Pointer to the data t } // End PCD_MIFARE_Transceive() /** - * Returns a string pointer to a status code name. + * Returns a __FlashStringHelper pointer to a status code name. * */ -const char *MFRC522::GetStatusCodeName(byte code ///< One of the StatusCode enums. +const __FlashStringHelper *MFRC522::GetStatusCodeName(byte code ///< One of the StatusCode enums. ) { switch (code) { - case STATUS_OK: return "Success."; break; - case STATUS_ERROR: return "Error in communication."; break; - case STATUS_COLLISION: return "Collission detected."; break; - case STATUS_TIMEOUT: return "Timeout in communication."; break; - case STATUS_NO_ROOM: return "A buffer is not big enough."; break; - case STATUS_INTERNAL_ERROR: return "Internal error in the code. Should not happen."; break; - case STATUS_INVALID: return "Invalid argument."; break; - case STATUS_CRC_WRONG: return "The CRC_A does not match."; break; - case STATUS_MIFARE_NACK: return "A MIFARE PICC responded with NAK."; break; - default: - return "Unknown error"; - break; + case STATUS_OK: return F("Success."); break; + case STATUS_ERROR: return F("Error in communication."); break; + case STATUS_COLLISION: return F("Collission detected."); break; + case STATUS_TIMEOUT: return F("Timeout in communication."); break; + case STATUS_NO_ROOM: return F("A buffer is not big enough."); break; + case STATUS_INTERNAL_ERROR: return F("Internal error in the code. Should not happen."); break; + case STATUS_INVALID: return F("Invalid argument."); break; + case STATUS_CRC_WRONG: return F("The CRC_A does not match."); break; + case STATUS_MIFARE_NACK: return F("A MIFARE PICC responded with NAK."); break; + default: return F("Unknown error"); break; } } // End GetStatusCodeName() @@ -1122,23 +1120,23 @@ byte MFRC522::PICC_GetType(byte sak ///< The SAK byte returned from PICC_Select } // End PICC_GetType() /** - * Returns a string pointer to the PICC type name. + * Returns a __FlashStringHelper pointer to the PICC type name. * */ -const char *MFRC522::PICC_GetTypeName(byte piccType ///< One of the PICC_Type enums. +const __FlashStringHelper *MFRC522::PICC_GetTypeName(byte piccType ///< One of the PICC_Type enums. ) { switch (piccType) { - case PICC_TYPE_ISO_14443_4: return "PICC compliant with ISO/IEC 14443-4"; break; - case PICC_TYPE_ISO_18092: return "PICC compliant with ISO/IEC 18092 (NFC)"; break; - case PICC_TYPE_MIFARE_MINI: return "MIFARE Mini, 320 bytes"; break; - case PICC_TYPE_MIFARE_1K: return "MIFARE 1KB"; break; - case PICC_TYPE_MIFARE_4K: return "MIFARE 4KB"; break; - case PICC_TYPE_MIFARE_UL: return "MIFARE Ultralight or Ultralight C"; break; - case PICC_TYPE_MIFARE_PLUS: return "MIFARE Plus"; break; - case PICC_TYPE_TNP3XXX: return "MIFARE TNP3XXX"; break; - case PICC_TYPE_NOT_COMPLETE: return "SAK indicates UID is not complete."; break; + case PICC_TYPE_ISO_14443_4: return F("PICC compliant with ISO/IEC 14443-4"); break; + case PICC_TYPE_ISO_18092: return F("PICC compliant with ISO/IEC 18092 (NFC)");break; + case PICC_TYPE_MIFARE_MINI: return F("MIFARE Mini, 320 bytes"); break; + case PICC_TYPE_MIFARE_1K: return F("MIFARE 1KB"); break; + case PICC_TYPE_MIFARE_4K: return F("MIFARE 4KB"); break; + case PICC_TYPE_MIFARE_UL: return F("MIFARE Ultralight or Ultralight C"); break; + case PICC_TYPE_MIFARE_PLUS: return F("MIFARE Plus"); break; + case PICC_TYPE_TNP3XXX: return F("MIFARE TNP3XXX"); break; + case PICC_TYPE_NOT_COMPLETE: return F("SAK indicates UID is not complete."); break; case PICC_TYPE_UNKNOWN: - default: return "Unknown type"; break; + default: return F("Unknown type"); break; } } // End PICC_GetTypeName() diff --git a/MFRC522.h b/MFRC522.h index 563dc1c..809146b 100644 --- a/MFRC522.h +++ b/MFRC522.h @@ -321,10 +321,14 @@ public: ///////////////////////////////////////////////////////////////////////////////////// // Support functions ///////////////////////////////////////////////////////////////////////////////////// - byte PCD_MIFARE_Transceive( byte *sendData, byte sendLen, bool acceptTimeout = false); - const char *GetStatusCodeName(byte code); + byte PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout = false); + // old function used too much memory, now name moved to flash; if you need char, copy from flash to memory + //const char *GetStatusCodeName(byte code); + const __FlashStringHelper *GetStatusCodeName(byte code); byte PICC_GetType(byte sak); - const char *PICC_GetTypeName(byte type); + // old function used too much memory, now name moved to flash; if you need char, copy from flash to memory + //const char *PICC_GetTypeName(byte type); + const __FlashStringHelper *PICC_GetTypeName(byte type); void PICC_DumpToSerial(Uid *uid); void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType, MIFARE_Key *key); void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector); From 26f95497ae96d1c8207f2b54b3adf6e9336bb174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Paaske=20T=C3=B8rholm?= Date: Wed, 11 Mar 2015 23:25:35 +0100 Subject: [PATCH 2/3] Implement method for performing self-test of firmware Closes #89 --- MFRC522.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ MFRC522.h | 1 + 2 files changed, 100 insertions(+) diff --git a/MFRC522.cpp b/MFRC522.cpp index 441f1e9..3f67779 100644 --- a/MFRC522.cpp +++ b/MFRC522.cpp @@ -272,6 +272,105 @@ void MFRC522::PCD_SetAntennaGain(byte mask) { } } // End PCD_SetAntennaGain() +/** + * Performs a self-test of the MFRC522 + * See 16.1.1 in http://www.nxp.com/documents/data_sheet/MFRC522.pdf + * + * @return Whether or not the test passed. + */ +bool MFRC522::PCD_PerformSelfTest() { + // This follows directly the steps outlined in 16.1.1 + + // 1. Perform a soft reset. + PCD_Reset(); + + // 2. Clear the internal buffer by writing 25 bytes of 00h + byte ZEROES[25] = {0x00}; + PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // flush the FIFO buffer + PCD_WriteRegister(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO + PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer + + // 3. Enable self-test + PCD_WriteRegister(AutoTestReg, 0x09); + + // 4. Write 00h to FIFO buffer + PCD_WriteRegister(FIFODataReg, 0x00); + + // 5. Start self-test by issuing the CalcCRC command + PCD_WriteRegister(CommandReg, PCD_CalcCRC); + + // 6. Wait for self-test to complete + word i; + byte n; + for (i = 0; i < 0xFF; i++) { + n = PCD_ReadRegister(DivIrqReg); // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved + if (n & 0x04) { // CRCIRq bit set - calculation done + break; + } + } + PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO. + + // 7. Read out resulting 64 bytes from the FIFO buffer. + byte result[64]; + PCD_ReadRegister(FIFODataReg, 64, result, 0); + + // Auto self-test done + + // Reset AutoTestReg register to be 0 again. Required for normal operation. + PCD_WriteRegister(AutoTestReg, 0x00); + + // Determine firmware version (see section 9.3.4.8 in spec) + byte version = PCD_ReadRegister(VersionReg); + + // Reference values based on firmware version; taken from 16.1.1 in spec. + // Version 1.0 + byte referenceV1_0[] = { + 0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C, + 0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73, + 0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A, + 0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E, + 0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC, + 0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41, + 0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02, + 0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79 + }; + + // Version 2.0 + byte referenceV2_0[] = { + 0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95, + 0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE, + 0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82, + 0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49, + 0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81, + 0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9, + 0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, + 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F + }; + + // Pick the appropriate reference values + byte *reference; + switch (version) { + case 0x91: // Version 1.0 + reference = referenceV1_0; + break; + case 0x92: // Version 2.0 + reference = referenceV2_0; + break; + default: // Unknown version + return false; + } + + // Verify that the results match up to our expectations + for (i = 0; i < 64; i++) { + if (result[i] != reference[i]) { + return false; + } + } + + // Test passed; all is good. + return true; +} // End PCD_PerformSelfTest() + ///////////////////////////////////////////////////////////////////////////////////// // Functions for communicating with PICCs ///////////////////////////////////////////////////////////////////////////////////// diff --git a/MFRC522.h b/MFRC522.h index 563dc1c..8a4e2ee 100644 --- a/MFRC522.h +++ b/MFRC522.h @@ -290,6 +290,7 @@ public: void PCD_AntennaOff(); byte PCD_GetAntennaGain(); void PCD_SetAntennaGain(byte mask); + bool PCD_PerformSelfTest(); ///////////////////////////////////////////////////////////////////////////////////// // Functions for communicating with PICCs From 038badba6c4b2f2ac5a422313bddaba6bc5c809f Mon Sep 17 00:00:00 2001 From: Rotzbua Date: Thu, 12 Mar 2015 15:26:43 +0100 Subject: [PATCH 3/3] move self-test reference from ram to flash --- MFRC522.cpp | 33 ++++----------------------------- MFRC522.h | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/MFRC522.cpp b/MFRC522.cpp index b745d58..8b20c0c 100644 --- a/MFRC522.cpp +++ b/MFRC522.cpp @@ -322,39 +322,14 @@ bool MFRC522::PCD_PerformSelfTest() { // Determine firmware version (see section 9.3.4.8 in spec) byte version = PCD_ReadRegister(VersionReg); - // Reference values based on firmware version; taken from 16.1.1 in spec. - // Version 1.0 - byte referenceV1_0[] = { - 0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C, - 0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73, - 0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A, - 0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E, - 0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC, - 0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41, - 0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02, - 0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79 - }; - - // Version 2.0 - byte referenceV2_0[] = { - 0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95, - 0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE, - 0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82, - 0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49, - 0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81, - 0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9, - 0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, - 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F - }; - // Pick the appropriate reference values - byte *reference; + const byte *reference; switch (version) { case 0x91: // Version 1.0 - reference = referenceV1_0; + reference = MFRC522_firmware_referenceV1_0; break; case 0x92: // Version 2.0 - reference = referenceV2_0; + reference = MFRC522_firmware_referenceV2_0; break; default: // Unknown version return false; @@ -362,7 +337,7 @@ bool MFRC522::PCD_PerformSelfTest() { // Verify that the results match up to our expectations for (i = 0; i < 64; i++) { - if (result[i] != reference[i]) { + if (result[i] != pgm_read_byte(&(reference[i]))) { return false; } } diff --git a/MFRC522.h b/MFRC522.h index 1b6a9bc..b0429dd 100644 --- a/MFRC522.h +++ b/MFRC522.h @@ -78,6 +78,31 @@ #include #include +// Firmware data for self-test +// Reference values based on firmware version; taken from 16.1.1 in spec. +// Version 1.0 +const byte MFRC522_firmware_referenceV1_0[] PROGMEM = { + 0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C, + 0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73, + 0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A, + 0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E, + 0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC, + 0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41, + 0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02, + 0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79 +}; +// Version 2.0 +const byte MFRC522_firmware_referenceV2_0[] PROGMEM = { + 0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95, + 0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE, + 0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82, + 0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49, + 0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81, + 0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9, + 0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, + 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F +}; + class MFRC522 { public: // MFRC522 registers. Described in chapter 9 of the datasheet.