Move strings to PROGMEM string tables

This frees up almost 1KB of dynamic memory.
This commit is contained in:
Sebastian Kurella
2015-01-30 15:29:39 +00:00
parent cd1bc210e2
commit 605a1d755f
2 changed files with 112 additions and 35 deletions

View File

@@ -6,6 +6,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <MFRC522.h> #include <MFRC522.h>
#include <avr/pgmspace.h>
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Functions for setting up the Arduino // 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. const char *MFRC522::GetStatusCodeName(byte code ///< One of the StatusCode enums.
) { ) {
switch (code) { if (code == 0 || code > STATUS_MIFARE_NACK) {
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"; return "Unknown error";
break;
} }
strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_StatusCodeName[code - 1])));
return stringBuffer;
} // End GetStatusCodeName() } // 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. const char *MFRC522::PICC_GetTypeName(byte piccType ///< One of the PICC_Type enums.
) { ) {
switch (piccType) { if (piccType == PICC_TYPE_UNKNOWN) {
case PICC_TYPE_ISO_14443_4: return "PICC compliant with ISO/IEC 14443-4"; break; strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_Error[ERR_PICC_TYPE_NOT_COMPLETE])));
case PICC_TYPE_ISO_18092: return "PICC compliant with ISO/IEC 18092 (NFC)"; break; } else {
case PICC_TYPE_MIFARE_MINI: return "MIFARE Mini, 320 bytes"; break; strcpy_P(stringBuffer, (char*)pgm_read_word(&(_MFRC522_str_PICC_TypeName[piccType])));
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;
} }
return stringBuffer;
} // End PICC_GetTypeName() } // 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_ISO_18092:
case PICC_TYPE_MIFARE_PLUS: case PICC_TYPE_MIFARE_PLUS:
case PICC_TYPE_TNP3XXX: 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; break;
case PICC_TYPE_UNKNOWN: 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 byte status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 40
if( status != STATUS_OK ) { if( status != STATUS_OK ) {
if( logErrors ) { 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.print("Error name: ");
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
@@ -1466,7 +1453,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) {
} }
if ( received != 1 || response[0] != 0x0A ) { if ( received != 1 || response[0] != 0x0A ) {
if ( logErrors ) { 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(response[0], HEX);
Serial.print(" ("); Serial.print(" (");
Serial.print(validBits); 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 status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 43
if( status != STATUS_OK ) { if( status != STATUS_OK ) {
if( logErrors ) { 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.print("Error name: ");
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
@@ -1488,7 +1477,8 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) {
} }
if ( received != 1 || response[0] != 0x0A ) { if ( received != 1 || response[0] != 0x0A ) {
if ( logErrors ) { 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(response[0], HEX);
Serial.print(" ("); Serial.print(" (");
Serial.print(validBits); 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 // UID + BCC byte can not be larger than 16 together
if ( !newUid || !uidSize || uidSize > 15) { if ( !newUid || !uidSize || uidSize > 15) {
if ( logErrors ) { 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; return false;
} }
@@ -1533,7 +1524,8 @@ bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) {
// PICC_WakeupA(atqa_answer, &atqa_size); // PICC_WakeupA(atqa_answer, &atqa_size);
if ( !PICC_IsNewCardPresent() || !PICC_ReadCardSerial() ) { 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; return false;
} }
@@ -1541,7 +1533,8 @@ bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) {
if ( status != STATUS_OK ) { if ( status != STATUS_OK ) {
// We tried, time to give up // We tried, time to give up
if ( logErrors ) { 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)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;

View File

@@ -78,6 +78,88 @@
#include <Arduino.h> #include <Arduino.h>
#include <SPI.h> #include <SPI.h>
/////////////////////////////////////////////////////////////////////////////////////
// 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 { class MFRC522 {
public: public:
// MFRC522 registers. Described in chapter 9 of the datasheet. // 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. 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 { enum PICC_Type {
PICC_TYPE_UNKNOWN = 0, PICC_TYPE_UNKNOWN = 0,
PICC_TYPE_ISO_14443_4 = 1, // PICC compliant with ISO/IEC 14443-4 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. 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 { enum StatusCode {
STATUS_OK = 1, // Success STATUS_OK = 1, // Success
STATUS_ERROR = 2, // Error in communication 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 _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 _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); byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data);
char stringBuffer[100];
}; };
#endif #endif