From 605a1d755f3762e037cb7545c5cd868794d66ce7 Mon Sep 17 00:00:00 2001 From: Sebastian Kurella Date: Fri, 30 Jan 2015 15:29:39 +0000 Subject: [PATCH] Move strings to PROGMEM string tables This frees up almost 1KB of dynamic memory. --- MFRC522.cpp | 59 ++++++++++++++++------------------- MFRC522.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 35 deletions(-) diff --git a/MFRC522.cpp b/MFRC522.cpp index 09e0c31..ad4495a 100644 --- a/MFRC522.cpp +++ b/MFRC522.cpp @@ -6,6 +6,7 @@ #include #include +#include ///////////////////////////////////////////////////////////////////////////////////// // Functions for setting up the Arduino @@ -1072,20 +1073,11 @@ byte MFRC522::PCD_MIFARE_Transceive( byte *sendData, ///< Pointer to the data t */ const char *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; + if (code == 0 || code > STATUS_MIFARE_NACK) { + return "Unknown error"; } + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_StatusCodeName[code - 1]))); + return stringBuffer; } // End GetStatusCodeName() /** @@ -1127,19 +1119,12 @@ byte MFRC522::PICC_GetType(byte sak ///< The SAK byte returned from PICC_Select */ const char *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_UNKNOWN: - default: return "Unknown type"; break; + if (piccType == PICC_TYPE_UNKNOWN) { + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_PICC_TYPE_NOT_COMPLETE]))); + } else { + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_PICC_TypeName[piccType]))); } + return stringBuffer; } // End PICC_GetTypeName() /** @@ -1184,7 +1169,8 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro case PICC_TYPE_ISO_18092: case PICC_TYPE_MIFARE_PLUS: case PICC_TYPE_TNP3XXX: - Serial.println("Dumping memory contents not implemented for that PICC type."); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_PICC_TYPE_TNP3XXX]))); + Serial.println(stringBuffer); break; case PICC_TYPE_UNKNOWN: @@ -1458,7 +1444,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { byte status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 40 if( status != STATUS_OK ) { if( logErrors ) { - Serial.println("Card did not respond to 0x40 after HALT command. Are you sure it is a UID changeable one?"); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_NO_RESPONSE_AFTER_HALT]))); + Serial.println(stringBuffer); Serial.print("Error name: "); Serial.println(GetStatusCodeName(status)); } @@ -1466,7 +1453,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { } if ( received != 1 || response[0] != 0x0A ) { if ( logErrors ) { - Serial.print("Got bad response on backdoor 0x40 command: "); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_COMMAND_0x40_RESPONSE]))); + Serial.print(stringBuffer); Serial.print(response[0], HEX); Serial.print(" ("); Serial.print(validBits); @@ -1480,7 +1468,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 43 if( status != STATUS_OK ) { if( logErrors ) { - Serial.println("Error in communication at command 0x43, after successfully executing 0x40"); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_COMMAND_0x43_COMM]))); + Serial.println(stringBuffer); Serial.print("Error name: "); Serial.println(GetStatusCodeName(status)); } @@ -1488,7 +1477,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { } if ( received != 1 || response[0] != 0x0A ) { if ( logErrors ) { - Serial.print("Got bad response on backdoor 0x43 command: "); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_COMMAND_0x43_RESPONSE]))); + Serial.print(stringBuffer); Serial.print(response[0], HEX); Serial.print(" ("); Serial.print(validBits); @@ -1514,7 +1504,8 @@ bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) { // UID + BCC byte can not be larger than 16 together if ( !newUid || !uidSize || uidSize > 15) { if ( logErrors ) { - Serial.println("New UID buffer empty, size 0, or size > 15 given"); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_WRONG_UID]))); + Serial.println(stringBuffer); } return false; } @@ -1533,7 +1524,8 @@ bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) { // PICC_WakeupA(atqa_answer, &atqa_size); if ( !PICC_IsNewCardPresent() || !PICC_ReadCardSerial() ) { - Serial.println("No card was previously selected, and none are available. Failed to set UID."); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_NO_CARD]))); + Serial.println(stringBuffer); return false; } @@ -1541,7 +1533,8 @@ bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) { if ( status != STATUS_OK ) { // We tried, time to give up if ( logErrors ) { - Serial.println("Failed to authenticate to card for reading, could not set UID: "); + strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_AUTH_KEY_A]))); + Serial.println(stringBuffer); Serial.println(GetStatusCodeName(status)); } return false; diff --git a/MFRC522.h b/MFRC522.h index 563dc1c..544edbf 100644 --- a/MFRC522.h +++ b/MFRC522.h @@ -78,6 +78,88 @@ #include #include +///////////////////////////////////////////////////////////////////////////////////// +// String tables to be stored in program memory +///////////////////////////////////////////////////////////////////////////////////// + +const char _MFRC522_str_STATUS_OK[] PROGMEM = "Success."; +const char _MFRC522_str_STATUS_ERROR[] PROGMEM = "Error in communication."; +const char _MFRC522_str_STATUS_COLLISION[] PROGMEM = "Collission detected."; +const char _MFRC522_str_STATUS_TIMEOUT[] PROGMEM = "Timeout in communication."; +const char _MFRC522_str_STATUS_NO_ROOM[] PROGMEM = "A buffer is not big enough."; +const char _MFRC522_str_STATUS_INTERNAL_ERROR[] PROGMEM = "Internal error in the code. Should not happen."; +const char _MFRC522_str_STATUS_INVALID[] PROGMEM = "Invalid argument."; +const char _MFRC522_str_STATUS_CRC_WRONG[] PROGMEM = "The CRC_A does not match."; +const char _MFRC522_str_STATUS_MIFARE_NACK[] PROGMEM = "A MIFARE PICC responded with NAK."; + +const char* const _MFRC522_str_StatusCodeName[] PROGMEM { + _MFRC522_str_STATUS_OK, + _MFRC522_str_STATUS_ERROR, + _MFRC522_str_STATUS_COLLISION, + _MFRC522_str_STATUS_TIMEOUT, + _MFRC522_str_STATUS_NO_ROOM, + _MFRC522_str_STATUS_INTERNAL_ERROR, + _MFRC522_str_STATUS_INVALID, + _MFRC522_str_STATUS_CRC_WRONG, + _MFRC522_str_STATUS_MIFARE_NACK +}; + +const char _MFRC522_str_PICC_TYPE_UNKNOWN[] PROGMEM = "Unknown type"; +const char _MFRC522_str_PICC_TYPE_ISO_14443_4[] PROGMEM = "PICC compliant with ISO/IEC 14443-4"; +const char _MFRC522_str_PICC_TYPE_ISO_18092[] PROGMEM = "PICC compliant with ISO/IEC 18092 (NFC)"; +const char _MFRC522_str_PICC_TYPE_MIFARE_MINI[] PROGMEM = "MIFARE Mini, 320 bytes"; +const char _MFRC522_str_PICC_TYPE_MIFARE_1K[] PROGMEM = "MIFARE 1KB"; +const char _MFRC522_str_PICC_TYPE_MIFARE_4K[] PROGMEM = "MIFARE 4KB"; +const char _MFRC522_str_PICC_TYPE_MIFARE_UL[] PROGMEM = "MIFARE Ultralight or Ultralight C"; +const char _MFRC522_str_PICC_TYPE_MIFARE_PLUS[] PROGMEM = "MIFARE Plus"; +const char _MFRC522_str_PICC_TYPE_TNP3XXX[] PROGMEM = "MIFARE TNP3XXX"; + +const char* const _MFRC522_str_PICC_TypeName[] PROGMEM { + _MFRC522_str_PICC_TYPE_UNKNOWN, + _MFRC522_str_PICC_TYPE_ISO_14443_4, + _MFRC522_str_PICC_TYPE_ISO_18092, + _MFRC522_str_PICC_TYPE_MIFARE_MINI, + _MFRC522_str_PICC_TYPE_MIFARE_1K, + _MFRC522_str_PICC_TYPE_MIFARE_4K, + _MFRC522_str_PICC_TYPE_MIFARE_UL, + _MFRC522_str_PICC_TYPE_MIFARE_PLUS, + _MFRC522_str_PICC_TYPE_TNP3XXX +}; + +const char _MFRC522_str_ERR_PICC_TYPE_NOT_COMPLETE[] PROGMEM = "SAK indicates UID is not complete."; +const char _MFRC522_str_ERR_PICC_TYPE_TNP3XXX[] PROGMEM = "Dumping memory contents not implemented for that PICC type."; +const char _MFRC522_str_ERR_NO_RESPONSE_AFTER_HALT[] PROGMEM = "Card did not respond to 0x40 after HALT command. Are you sure it is a UID changeable one?"; +const char _MFRC522_str_ERR_COMMAND_0x40_RESPONSE[] PROGMEM = "Got bad response on backdoor 0x40 command: "; +const char _MFRC522_str_ERR_COMMAND_0x43_COMM[] PROGMEM = "Error in communication at command 0x43, after successfully executing 0x40"; +const char _MFRC522_str_ERR_COMMAND_0x43_RESPONSE[] PROGMEM = "Got bad response on backdoor 0x43 command: "; +const char _MFRC522_str_ERR_WRONG_UID[] PROGMEM = "New UID buffer empty, size 0, or size > 15 given"; +const char _MFRC522_str_ERR_NO_CARD[] PROGMEM = "No card was previously selected, and none are available. Failed to set UID."; +const char _MFRC522_str_ERR_AUTH_KEY_A[] PROGMEM = "Failed to authenticate to card for reading, could not set UID: "; + +enum _MFRC522_str_Error { + ERR_PICC_TYPE_NOT_COMPLETE, + ERR_PICC_TYPE_TNP3XXX, + ERR_NO_RESPONSE_AFTER_HALT, + ERR_COMMAND_0x40_RESPONSE, + ERR_COMMAND_0x43_COMM, + ERR_COMMAND_0x43_RESPONSE, + ERR_WRONG_UID, + ERR_NO_CARD, + ERR_AUTH_KEY_A +}; + +const char* const _MFRC522_str_Error[] PROGMEM { + _MFRC522_str_ERR_PICC_TYPE_NOT_COMPLETE, + _MFRC522_str_ERR_PICC_TYPE_TNP3XXX, + _MFRC522_str_ERR_NO_RESPONSE_AFTER_HALT, + _MFRC522_str_ERR_COMMAND_0x40_RESPONSE, + _MFRC522_str_ERR_COMMAND_0x43_COMM, + _MFRC522_str_ERR_COMMAND_0x43_RESPONSE, + _MFRC522_str_ERR_WRONG_UID, + _MFRC522_str_ERR_NO_CARD, + _MFRC522_str_ERR_AUTH_KEY_A +}; + class MFRC522 { public: // MFRC522 registers. Described in chapter 9 of the datasheet. @@ -218,7 +300,7 @@ public: MF_KEY_SIZE = 6 // A Mifare Crypto1 key is 6 bytes. }; - // PICC types we can detect. Remember to update PICC_GetTypeName() if you add more. + // PICC types we can detect. Remember to update string tables and PICC_GetTypeName() if you add more. enum PICC_Type { PICC_TYPE_UNKNOWN = 0, PICC_TYPE_ISO_14443_4 = 1, // PICC compliant with ISO/IEC 14443-4 @@ -232,7 +314,7 @@ public: PICC_TYPE_NOT_COMPLETE = 255 // SAK indicates UID is not complete. }; - // Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more. + // Return codes from the functions in this class. Remember to update string tables and GetStatusCodeName() if you add more. enum StatusCode { STATUS_OK = 1, // Success STATUS_ERROR = 2, // Error in communication @@ -344,6 +426,8 @@ private: byte _chipSelectPin; // Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low) byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low) byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data); + + char stringBuffer[100]; }; #endif