From 1beea0c586071957d1eb159860b543bd544cb170 Mon Sep 17 00:00:00 2001 From: David Conran <crankyoldgit@users.noreply.github.com> Date: Sat, 9 Oct 2021 08:04:55 +1000 Subject: [PATCH] Strings finally in Flash! (#1623) Finally convince the compiler to store the text strings into flash. Saves approx 2k of Global ram, for a trade-off of between ~0-0.5k of extra flash space used. e.g. _(updated)_ * IRMQTTServer example code: - Before: RAM: [===== ] 54.1% (used 44344 bytes from 81920 bytes) Flash: [===== ] 54.2% (used 566209 bytes from 1044464 bytes) Bin file size = 570368 - After: RAM: [===== ] 51.3% (used 41992 bytes from 81920 bytes) Flash: [===== ] 54.2% (used 566201 bytes from 1044464 bytes) Bin file size = 570352 * IRrecvDumpV2 example code: - Before: RAM: [==== ] 37.9% (used 31044 bytes from 81920 bytes) Flash: [==== ] 35.6% (used 372025 bytes from 1044464 bytes) Bin file size = 376176 - After: RAM: [==== ] 35.5% (used 29072 bytes from 81920 bytes) Flash: [==== ] 35.7% (used 372525 bytes from 1044464 bytes) Bin file size = 376672 Fixes #1614 Fixes #1493 Co-authored with @mcspr --- keywords.txt | 47 ++++- src/IRac.cpp | 248 +++++++++++++++------------ src/IRtext.cpp | 340 ++++++++++++++++++++----------------- src/IRtext.h | 322 ++++++++++++++++++----------------- src/IRutils.cpp | 52 ++++-- src/ir_Electra.cpp | 3 +- src/ir_Goodweather.cpp | 10 +- src/ir_Sharp.cpp | 11 +- tools/generate_irtext_h.sh | 16 +- tools/mkkeywords | 13 +- 10 files changed, 605 insertions(+), 457 deletions(-) diff --git a/keywords.txt b/keywords.txt index fefce8d9d..60e714c5d 100644 --- a/keywords.txt +++ b/keywords.txt @@ -95,6 +95,7 @@ sharp_ac_remote_model_t KEYWORD1 state_t KEYWORD1 swingh_t KEYWORD1 swingv_t KEYWORD1 +tcl_ac_remote_model_t KEYWORD1 voltas_ac_remote_model_t KEYWORD1 whirlpool_ac_remote_model_t KEYWORD1 @@ -193,6 +194,7 @@ decodeAirwell KEYWORD2 decodeAiwaRCT501 KEYWORD2 decodeAmcor KEYWORD2 decodeArgo KEYWORD2 +decodeArris KEYWORD2 decodeBose KEYWORD2 decodeCOOLIX KEYWORD2 decodeCarrierAC KEYWORD2 @@ -298,6 +300,7 @@ enableIROut KEYWORD2 enableOffTimer KEYWORD2 enableOnTimer KEYWORD2 enableSleepTimer KEYWORD2 +encodeArris KEYWORD2 encodeDoshisha KEYWORD2 encodeJVC KEYWORD2 encodeLG KEYWORD2 @@ -481,6 +484,7 @@ isSwingH KEYWORD2 isSwingV KEYWORD2 isSwingVStep KEYWORD2 isSwingVToggle KEYWORD2 +isTcl KEYWORD2 isTimeCommand KEYWORD2 isTimerActive KEYWORD2 isTurboToggle KEYWORD2 @@ -541,6 +545,7 @@ sendAirwell KEYWORD2 sendAiwaRCT501 KEYWORD2 sendAmcor KEYWORD2 sendArgo KEYWORD2 +sendArris KEYWORD2 sendBose KEYWORD2 sendCOOLIX KEYWORD2 sendCarrierAC KEYWORD2 @@ -791,6 +796,7 @@ teco KEYWORD2 ticksHigh KEYWORD2 ticksLow KEYWORD2 toString KEYWORD2 +toggleArrisRelease KEYWORD2 toggleRC5 KEYWORD2 toggleRC6 KEYWORD2 toggleSwingHoriz KEYWORD2 @@ -857,6 +863,7 @@ ARJW2 LITERAL1 ARRAH2E LITERAL1 ARREB1E LITERAL1 ARREW4E LITERAL1 +ARRIS LITERAL1 ARRY4 LITERAL1 BOSE LITERAL1 CARRIER_AC LITERAL1 @@ -891,6 +898,7 @@ DECODE_AIRWELL LITERAL1 DECODE_AIWA_RC_T501 LITERAL1 DECODE_AMCOR LITERAL1 DECODE_ARGO LITERAL1 +DECODE_ARRIS LITERAL1 DECODE_BOSE LITERAL1 DECODE_CARRIER_AC LITERAL1 DECODE_CARRIER_AC40 LITERAL1 @@ -1054,6 +1062,7 @@ GREE_SWING_MIDDLE_DOWN LITERAL1 GREE_SWING_MIDDLE_UP LITERAL1 GREE_SWING_UP LITERAL1 GREE_SWING_UP_AUTO LITERAL1 +GZ055BE1 LITERAL1 HAIER_AC LITERAL1 HAIER_AC176 LITERAL1 HAIER_AC_AUTO LITERAL1 @@ -1213,6 +1222,7 @@ PANASONIC_BITS LITERAL1 PIONEER LITERAL1 PROGMEM LITERAL1 PRONTO LITERAL1 +PSTR LITERAL1 RAW LITERAL1 RAWTICK LITERAL1 RC5 LITERAL1 @@ -1240,6 +1250,7 @@ SEND_AIRWELL LITERAL1 SEND_AIWA_RC_T501 LITERAL1 SEND_AMCOR LITERAL1 SEND_ARGO LITERAL1 +SEND_ARRIS LITERAL1 SEND_BOSE LITERAL1 SEND_CARRIER_AC LITERAL1 SEND_CARRIER_AC40 LITERAL1 @@ -1347,6 +1358,7 @@ SONY_15_BITS LITERAL1 SONY_20_BITS LITERAL1 SONY_38K LITERAL1 SYMPHONY LITERAL1 +TAC09CHSD LITERAL1 TCL112AC LITERAL1 TECHNIBEL_AC LITERAL1 TECO LITERAL1 @@ -1497,6 +1509,16 @@ kArgoOneSpace LITERAL1 kArgoStateLength LITERAL1 kArgoTempDelta LITERAL1 kArgoZeroSpace LITERAL1 +kArrisBits LITERAL1 +kArrisChecksumSize LITERAL1 +kArrisCommandSize LITERAL1 +kArrisGapSpace LITERAL1 +kArrisHalfClockPeriod LITERAL1 +kArrisHdrMark LITERAL1 +kArrisHdrSpace LITERAL1 +kArrisOverhead LITERAL1 +kArrisReleaseBit LITERAL1 +kArrisReleaseToggle LITERAL1 kAuto LITERAL1 kAutoStr LITERAL1 kAutomaticStr LITERAL1 @@ -2008,8 +2030,11 @@ kEyeAutoStr LITERAL1 kEyeStr LITERAL1 kFalseStr LITERAL1 kFan LITERAL1 +kFanOnlyNoSpaceStr LITERAL1 kFanOnlyStr LITERAL1 +kFanOnlyWithSpaceStr LITERAL1 kFanStr LITERAL1 +kFan_OnlyStr LITERAL1 kFastStr LITERAL1 kFilterStr LITERAL1 kFixedStr LITERAL1 @@ -3326,8 +3351,15 @@ kSharpAcSpecialTimer LITERAL1 kSharpAcSpecialTimerHalfHour LITERAL1 kSharpAcSpecialTurbo LITERAL1 kSharpAcStateLength LITERAL1 -kSharpAcSwingNoToggle LITERAL1 -kSharpAcSwingToggle LITERAL1 +kSharpAcSwingVCoanda LITERAL1 +kSharpAcSwingVHigh LITERAL1 +kSharpAcSwingVIgnore LITERAL1 +kSharpAcSwingVLast LITERAL1 +kSharpAcSwingVLow LITERAL1 +kSharpAcSwingVLowest LITERAL1 +kSharpAcSwingVMid LITERAL1 +kSharpAcSwingVOff LITERAL1 +kSharpAcSwingVToggle LITERAL1 kSharpAcTimerHoursMax LITERAL1 kSharpAcTimerHoursOff LITERAL1 kSharpAcTimerIncrement LITERAL1 @@ -3408,6 +3440,9 @@ kTcl112AcFanAuto LITERAL1 kTcl112AcFanHigh LITERAL1 kTcl112AcFanLow LITERAL1 kTcl112AcFanMed LITERAL1 +kTcl112AcFanMin LITERAL1 +kTcl112AcFanNight LITERAL1 +kTcl112AcFanQuiet LITERAL1 kTcl112AcGap LITERAL1 kTcl112AcHdrMark LITERAL1 kTcl112AcHdrMarkTolerance LITERAL1 @@ -3417,10 +3452,17 @@ kTcl112AcNormal LITERAL1 kTcl112AcOneSpace LITERAL1 kTcl112AcSpecial LITERAL1 kTcl112AcStateLength LITERAL1 +kTcl112AcSwingVHigh LITERAL1 +kTcl112AcSwingVHighest LITERAL1 +kTcl112AcSwingVLow LITERAL1 +kTcl112AcSwingVLowest LITERAL1 +kTcl112AcSwingVMiddle LITERAL1 kTcl112AcSwingVOff LITERAL1 kTcl112AcSwingVOn LITERAL1 kTcl112AcTempMax LITERAL1 kTcl112AcTempMin LITERAL1 +kTcl112AcTimerMax LITERAL1 +kTcl112AcTimerResolution LITERAL1 kTcl112AcTolerance LITERAL1 kTcl112AcZeroSpace LITERAL1 kTechnibelAcBitMark LITERAL1 @@ -3482,6 +3524,7 @@ kTempDownStr LITERAL1 kTempStr LITERAL1 kTempUpStr LITERAL1 kThreeLetterDayOfWeekStr LITERAL1 +kTimeSep LITERAL1 kTimeoutMs LITERAL1 kTimerModeStr LITERAL1 kTimerStr LITERAL1 diff --git a/src/IRac.cpp b/src/IRac.cpp index 9379914b1..9623c98d7 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -50,6 +50,20 @@ #include "ir_Voltas.h" #include "ir_Whirlpool.h" +// On the ESP8266 platform we need to use a special version of string handling +// functions to handle the strings stored in the flash address space. +#ifndef STRCASECMP +#if defined(ESP8266) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast<const char* const>(RHS)) +#else // ESP8266 +#define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS) +#endif // ESP8266 +#endif // STRCASECMP +#ifndef PSTR +#define PSTR +#endif + /// Class constructor /// @param[in] pin Gpio pin to use when transmitting IR messages. /// @param[in] inverted true, gpio output defaults to high. false, to low. @@ -3059,31 +3073,31 @@ bool IRac::hasStateChanged(void) { return cmpStates(next, _prev); } /// @return The equivalent enum. stdAc::opmode_t IRac::strToOpmode(const char *str, const stdAc::opmode_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr)) return stdAc::opmode_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::opmode_t::kOff; - else if (!strcasecmp(str, kCoolStr) || - !strcasecmp(str, "COOLING")) + else if (!STRCASECMP(str, kCoolStr) || + !STRCASECMP(str, PSTR("COOLING"))) return stdAc::opmode_t::kCool; - else if (!strcasecmp(str, kHeatStr) || - !strcasecmp(str, "HEATING")) + else if (!STRCASECMP(str, kHeatStr) || + !STRCASECMP(str, PSTR("HEATING"))) return stdAc::opmode_t::kHeat; - else if (!strcasecmp(str, kDryStr) || - !strcasecmp(str, "DRYING") || - !strcasecmp(str, "DEHUMIDIFY")) + else if (!STRCASECMP(str, kDryStr) || + !STRCASECMP(str, PSTR("DRYING")) || + !STRCASECMP(str, PSTR("DEHUMIDIFY"))) return stdAc::opmode_t::kDry; - else if (!strcasecmp(str, kFanStr) || + else if (!STRCASECMP(str, kFanStr) || // The following Fans strings with "only" are required to help with // HomeAssistant & Google Home Climate integration. // For compatibility only. // Ref: https://www.home-assistant.io/integrations/google_assistant/#climate-operation-modes - !strcasecmp(str, kFanOnlyStr) || - !strcasecmp(str, kFan_OnlyStr) || - !strcasecmp(str, kFanOnlyWithSpaceStr) || - !strcasecmp(str, kFanOnlyNoSpaceStr)) + !STRCASECMP(str, kFanOnlyStr) || + !STRCASECMP(str, kFan_OnlyStr) || + !STRCASECMP(str, kFanOnlyWithSpaceStr) || + !STRCASECMP(str, kFanOnlyNoSpaceStr)) return stdAc::opmode_t::kFan; else return def; @@ -3095,26 +3109,26 @@ stdAc::opmode_t IRac::strToOpmode(const char *str, /// @return The equivalent enum. stdAc::fanspeed_t IRac::strToFanspeed(const char *str, const stdAc::fanspeed_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr)) return stdAc::fanspeed_t::kAuto; - else if (!strcasecmp(str, kMinStr) || - !strcasecmp(str, kMinimumStr) || - !strcasecmp(str, kLowestStr)) + else if (!STRCASECMP(str, kMinStr) || + !STRCASECMP(str, kMinimumStr) || + !STRCASECMP(str, kLowestStr)) return stdAc::fanspeed_t::kMin; - else if (!strcasecmp(str, kLowStr) || - !strcasecmp(str, kLoStr)) + else if (!STRCASECMP(str, kLowStr) || + !STRCASECMP(str, kLoStr)) return stdAc::fanspeed_t::kLow; - else if (!strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kMidStr)) + else if (!STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kMidStr)) return stdAc::fanspeed_t::kMedium; - else if (!strcasecmp(str, kHighStr) || - !strcasecmp(str, kHiStr)) + else if (!STRCASECMP(str, kHighStr) || + !STRCASECMP(str, kHiStr)) return stdAc::fanspeed_t::kHigh; - else if (!strcasecmp(str, kMaxStr) || - !strcasecmp(str, kMaximumStr) || - !strcasecmp(str, kHighestStr)) + else if (!STRCASECMP(str, kMaxStr) || + !STRCASECMP(str, kMaximumStr) || + !STRCASECMP(str, kHighestStr)) return stdAc::fanspeed_t::kMax; else return def; @@ -3126,36 +3140,36 @@ stdAc::fanspeed_t IRac::strToFanspeed(const char *str, /// @return The equivalent enum. stdAc::swingv_t IRac::strToSwingV(const char *str, const stdAc::swingv_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr) || - !strcasecmp(str, kOnStr) || - !strcasecmp(str, kSwingStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr) || + !STRCASECMP(str, kOnStr) || + !STRCASECMP(str, kSwingStr)) return stdAc::swingv_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::swingv_t::kOff; - else if (!strcasecmp(str, kMinStr) || - !strcasecmp(str, kMinimumStr) || - !strcasecmp(str, kLowestStr) || - !strcasecmp(str, kBottomStr) || - !strcasecmp(str, kDownStr)) + else if (!STRCASECMP(str, kMinStr) || + !STRCASECMP(str, kMinimumStr) || + !STRCASECMP(str, kLowestStr) || + !STRCASECMP(str, kBottomStr) || + !STRCASECMP(str, kDownStr)) return stdAc::swingv_t::kLowest; - else if (!strcasecmp(str, kLowStr)) + else if (!STRCASECMP(str, kLowStr)) return stdAc::swingv_t::kLow; - else if (!strcasecmp(str, kMidStr) || - !strcasecmp(str, kMiddleStr) || - !strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kCentreStr)) + else if (!STRCASECMP(str, kMidStr) || + !STRCASECMP(str, kMiddleStr) || + !STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kCentreStr)) return stdAc::swingv_t::kMiddle; - else if (!strcasecmp(str, kHighStr) || - !strcasecmp(str, kHiStr)) + else if (!STRCASECMP(str, kHighStr) || + !STRCASECMP(str, kHiStr)) return stdAc::swingv_t::kHigh; - else if (!strcasecmp(str, kHighestStr) || - !strcasecmp(str, kMaxStr) || - !strcasecmp(str, kMaximumStr) || - !strcasecmp(str, kTopStr) || - !strcasecmp(str, kUpStr)) + else if (!STRCASECMP(str, kHighestStr) || + !STRCASECMP(str, kMaxStr) || + !STRCASECMP(str, kMaximumStr) || + !STRCASECMP(str, kTopStr) || + !STRCASECMP(str, kUpStr)) return stdAc::swingv_t::kHighest; else return def; @@ -3167,34 +3181,34 @@ stdAc::swingv_t IRac::strToSwingV(const char *str, /// @return The equivalent enum. stdAc::swingh_t IRac::strToSwingH(const char *str, const stdAc::swingh_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr) || - !strcasecmp(str, kOnStr) || !strcasecmp(str, kSwingStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr) || + !STRCASECMP(str, kOnStr) || !STRCASECMP(str, kSwingStr)) return stdAc::swingh_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::swingh_t::kOff; - else if (!strcasecmp(str, kLeftMaxStr) || // "LeftMax" - !strcasecmp(str, D_STR_LEFT " " D_STR_MAX) || // "Left Max" - !strcasecmp(str, D_STR_MAX D_STR_LEFT) || // "MaxLeft" - !strcasecmp(str, kMaxLeftStr)) // "Max Left" + else if (!STRCASECMP(str, kLeftMaxStr) || // "LeftMax" + !STRCASECMP(str, PSTR(D_STR_LEFT " " D_STR_MAX)) || // "Left Max" + !STRCASECMP(str, PSTR(D_STR_MAX D_STR_LEFT)) || // "MaxLeft" + !STRCASECMP(str, kMaxLeftStr)) // "Max Left" return stdAc::swingh_t::kLeftMax; - else if (!strcasecmp(str, kLeftStr)) + else if (!STRCASECMP(str, kLeftStr)) return stdAc::swingh_t::kLeft; - else if (!strcasecmp(str, kMidStr) || - !strcasecmp(str, kMiddleStr) || - !strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kCentreStr)) + else if (!STRCASECMP(str, kMidStr) || + !STRCASECMP(str, kMiddleStr) || + !STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kCentreStr)) return stdAc::swingh_t::kMiddle; - else if (!strcasecmp(str, kRightStr)) + else if (!STRCASECMP(str, kRightStr)) return stdAc::swingh_t::kRight; - else if (!strcasecmp(str, kRightMaxStr) || // "RightMax" - !strcasecmp(str, D_STR_RIGHT " " D_STR_MAX) || // "Right Max" - !strcasecmp(str, D_STR_MAX D_STR_RIGHT) || // "MaxRight" - !strcasecmp(str, kMaxRightStr)) // "Max Right" + else if (!STRCASECMP(str, kRightMaxStr) || // "RightMax" + !STRCASECMP(str, PSTR(D_STR_RIGHT " " D_STR_MAX)) || // "Right Max" + !STRCASECMP(str, PSTR(D_STR_MAX D_STR_RIGHT)) || // "MaxRight" + !STRCASECMP(str, kMaxRightStr)) // "Max Right" return stdAc::swingh_t::kRightMax; - else if (!strcasecmp(str, kWideStr)) + else if (!STRCASECMP(str, kWideStr)) return stdAc::swingh_t::kWide; else return def; @@ -3207,69 +3221,77 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, /// @return The equivalent enum. int16_t IRac::strToModel(const char *str, const int16_t def) { // Gree - if (!strcasecmp(str, "YAW1F")) { + if (!STRCASECMP(str, PSTR("YAW1F"))) { return gree_ac_remote_model_t::YAW1F; - } else if (!strcasecmp(str, "YBOFB")) { + } else if (!STRCASECMP(str, PSTR("YBOFB"))) { return gree_ac_remote_model_t::YBOFB; // HitachiAc1 models - } else if (!strcasecmp(str, "R-LT0541-HTA-A")) { + } else if (!STRCASECMP(str, PSTR("R-LT0541-HTA-A"))) { return hitachi_ac1_remote_model_t::R_LT0541_HTA_A; - } else if (!strcasecmp(str, "R-LT0541-HTA-B")) { + } else if (!STRCASECMP(str, PSTR("R-LT0541-HTA-B"))) { return hitachi_ac1_remote_model_t::R_LT0541_HTA_B; // Fujitsu A/C models - } else if (!strcasecmp(str, "ARRAH2E")) { + } else if (!STRCASECMP(str, PSTR("ARRAH2E"))) { return fujitsu_ac_remote_model_t::ARRAH2E; - } else if (!strcasecmp(str, "ARDB1")) { + } else if (!STRCASECMP(str, PSTR("ARDB1"))) { return fujitsu_ac_remote_model_t::ARDB1; - } else if (!strcasecmp(str, "ARREB1E")) { + } else if (!STRCASECMP(str, PSTR("ARREB1E"))) { return fujitsu_ac_remote_model_t::ARREB1E; - } else if (!strcasecmp(str, "ARJW2")) { + } else if (!STRCASECMP(str, PSTR("ARJW2"))) { return fujitsu_ac_remote_model_t::ARJW2; - } else if (!strcasecmp(str, "ARRY4")) { + } else if (!STRCASECMP(str, PSTR("ARRY4"))) { return fujitsu_ac_remote_model_t::ARRY4; // LG A/C models - } else if (!strcasecmp(str, "GE6711AR2853M")) { + } else if (!STRCASECMP(str, PSTR("GE6711AR2853M"))) { return lg_ac_remote_model_t::GE6711AR2853M; - } else if (!strcasecmp(str, "AKB75215403")) { + } else if (!STRCASECMP(str, PSTR("AKB75215403"))) { return lg_ac_remote_model_t::AKB75215403; - } else if (!strcasecmp(str, "AKB74955603")) { + } else if (!STRCASECMP(str, PSTR("AKB74955603"))) { return lg_ac_remote_model_t::AKB74955603; - } else if (!strcasecmp(str, "AKB73757604")) { + } else if (!STRCASECMP(str, PSTR("AKB73757604"))) { return lg_ac_remote_model_t::AKB73757604; // Panasonic A/C families - } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) { + } else if (!STRCASECMP(str, PSTR("LKE")) || + !STRCASECMP(str, PSTR("PANASONICLKE"))) { return panasonic_ac_remote_model_t::kPanasonicLke; - } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) { + } else if (!STRCASECMP(str, PSTR("NKE")) || + !STRCASECMP(str, PSTR("PANASONICNKE"))) { return panasonic_ac_remote_model_t::kPanasonicNke; - } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE") || - !strcasecmp(str, "PKR") || !strcasecmp(str, "PANASONICPKR")) { + } else if (!STRCASECMP(str, PSTR("DKE")) || + !STRCASECMP(str, PSTR("PANASONICDKE")) || + !STRCASECMP(str, PSTR("PKR")) || + !STRCASECMP(str, PSTR("PANASONICPKR"))) { return panasonic_ac_remote_model_t::kPanasonicDke; - } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) { + } else if (!STRCASECMP(str, PSTR("JKE")) || + !STRCASECMP(str, PSTR("PANASONICJKE"))) { return panasonic_ac_remote_model_t::kPanasonicJke; - } else if (!strcasecmp(str, "CKP") || !strcasecmp(str, "PANASONICCKP")) { + } else if (!STRCASECMP(str, PSTR("CKP")) || + !STRCASECMP(str, PSTR("PANASONICCKP"))) { return panasonic_ac_remote_model_t::kPanasonicCkp; - } else if (!strcasecmp(str, "RKR") || !strcasecmp(str, "PANASONICRKR")) { + } else if (!STRCASECMP(str, PSTR("RKR")) || + !STRCASECMP(str, PSTR("PANASONICRKR"))) { return panasonic_ac_remote_model_t::kPanasonicRkr; // Sharp A/C Models - } else if (!strcasecmp(str, "A907")) { + } else if (!STRCASECMP(str, PSTR("A907"))) { return sharp_ac_remote_model_t::A907; - } else if (!strcasecmp(str, "A705")) { + } else if (!STRCASECMP(str, PSTR("A705"))) { return sharp_ac_remote_model_t::A705; - } else if (!strcasecmp(str, "A903")) { + } else if (!STRCASECMP(str, PSTR("A903"))) { return sharp_ac_remote_model_t::A903; // TCL A/C Models - } else if (!strcasecmp(str, "TAC09CHSD")) { + } else if (!STRCASECMP(str, PSTR("TAC09CHSD"))) { return tcl_ac_remote_model_t::TAC09CHSD; - } else if (!strcasecmp(str, "GZ055BE1")) { + } else if (!STRCASECMP(str, PSTR("GZ055BE1"))) { return tcl_ac_remote_model_t::GZ055BE1; // Voltas A/C models - } else if (!strcasecmp(str, "122LZF")) { + } else if (!STRCASECMP(str, PSTR("122LZF"))) { return voltas_ac_remote_model_t::kVoltas122LZF; // Whirlpool A/C models - } else if (!strcasecmp(str, "DG11J13A") || !strcasecmp(str, "DG11J104") || - !strcasecmp(str, "DG11J1-04")) { + } else if (!STRCASECMP(str, PSTR("DG11J13A")) || + !STRCASECMP(str, PSTR("DG11J104")) || + !STRCASECMP(str, PSTR("DG11J1-04"))) { return whirlpool_ac_remote_model_t::DG11J13A; - } else if (!strcasecmp(str, "DG11J191")) { + } else if (!STRCASECMP(str, PSTR("DG11J191"))) { return whirlpool_ac_remote_model_t::DG11J191; } else { int16_t number = atoi(str); @@ -3285,15 +3307,15 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { /// @param[in] def The boolean value to return if no conversion was possible. /// @return The equivalent boolean value. bool IRac::strToBool(const char *str, const bool def) { - if (!strcasecmp(str, kOnStr) || - !strcasecmp(str, "1") || - !strcasecmp(str, kYesStr) || - !strcasecmp(str, kTrueStr)) + if (!STRCASECMP(str, kOnStr) || + !STRCASECMP(str, PSTR("1")) || + !STRCASECMP(str, kYesStr) || + !STRCASECMP(str, kTrueStr)) return true; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, "0") || - !strcasecmp(str, kNoStr) || - !strcasecmp(str, kFalseStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, PSTR("0")) || + !STRCASECMP(str, kNoStr) || + !STRCASECMP(str, kFalseStr)) return false; else return def; diff --git a/src/IRtext.cpp b/src/IRtext.cpp index a8959d43e..8cca392b3 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -1,9 +1,10 @@ -// Copyright 2019-2020 - David Conran (@crankyoldgit) +// Copyright 2019-2021 - David Conran (@crankyoldgit) /// @file IRtext.cpp /// @warning If you add or remove an entry in this file, you should run: /// '../tools/generate_irtext_h.sh' to rebuild the `IRtext.h` file. +#include "IRtext.h" #ifndef UNIT_TEST #include <Arduino.h> #endif // UNIT_TEST @@ -14,185 +15,205 @@ #define PROGMEM // Pretend we have the PROGMEM macro even if we really don't. #endif +#ifndef FPSTR +#define FPSTR(X) X // Also pretend we have flash-string helper class cast. +#endif + +#define IRTEXT_CONST_BLOB_NAME(NAME)\ + NAME ## Blob + +#define IRTEXT_CONST_BLOB_DECL(NAME)\ + const char IRTEXT_CONST_BLOB_NAME(NAME) [] PROGMEM + +#define IRTEXT_CONST_BLOB_PTR(NAME)\ + IRTEXT_CONST_PTR(NAME) {\ + IRTEXT_CONST_PTR_CAST(IRTEXT_CONST_BLOB_NAME(NAME)) } + +#define IRTEXT_CONST_STRING(NAME, VALUE)\ + static IRTEXT_CONST_BLOB_DECL(NAME) { VALUE };\ + IRTEXT_CONST_PTR(NAME) PROGMEM {\ + IRTEXT_CONST_PTR_CAST(&(IRTEXT_CONST_BLOB_NAME(NAME))[0]) } + // Common -const PROGMEM char* kUnknownStr = D_STR_UNKNOWN; ///< "Unknown" -const PROGMEM char* kProtocolStr = D_STR_PROTOCOL; ///< "Protocol" -const PROGMEM char* kPowerStr = D_STR_POWER; ///< "Power" -const PROGMEM char* kOnStr = D_STR_ON; ///< "On" -const PROGMEM char* kOffStr = D_STR_OFF; ///< "Off" -const PROGMEM char* kModeStr = D_STR_MODE; ///< "Mode" -const PROGMEM char* kToggleStr = D_STR_TOGGLE; ///< "Toggle" -const PROGMEM char* kTurboStr = D_STR_TURBO; ///< "Turbo" -const PROGMEM char* kSuperStr = D_STR_SUPER; ///< "Super" -const PROGMEM char* kSleepStr = D_STR_SLEEP; ///< "Sleep" -const PROGMEM char* kLightStr = D_STR_LIGHT; ///< "Light" -const PROGMEM char* kPowerfulStr = D_STR_POWERFUL; ///< "Powerful" -const PROGMEM char* kQuietStr = D_STR_QUIET; ///< "Quiet" -const PROGMEM char* kEconoStr = D_STR_ECONO; ///< "Econo" -const PROGMEM char* kSwingStr = D_STR_SWING; ///< "Swing" -const PROGMEM char* kSwingHStr = D_STR_SWINGH; ///< "SwingH" -const PROGMEM char* kSwingVStr = D_STR_SWINGV; ///< "SwingV" -const PROGMEM char* kBeepStr = D_STR_BEEP; ///< "Beep" -const PROGMEM char* kZoneFollowStr = D_STR_ZONEFOLLOW; ///< "Zone Follow" -const PROGMEM char* kFixedStr = D_STR_FIXED; ///< "Fixed" -const PROGMEM char* kMouldStr = D_STR_MOULD; ///< "Mould" -const PROGMEM char* kCleanStr = D_STR_CLEAN; ///< "Clean" -const PROGMEM char* kPurifyStr = D_STR_PURIFY; ///< "Purify" -const PROGMEM char* kTimerStr = D_STR_TIMER; ///< "Timer" -const PROGMEM char* kOnTimerStr = D_STR_ONTIMER; ///< "On Timer" -const PROGMEM char* kOffTimerStr = D_STR_OFFTIMER; ///< "Off Timer" -const PROGMEM char* kTimerModeStr = D_STR_TIMERMODE; ///< "Timer Mode" -const PROGMEM char* kClockStr = D_STR_CLOCK; ///< "Clock" -const PROGMEM char* kCommandStr = D_STR_COMMAND; ///< "Command" -const PROGMEM char* kXFanStr = D_STR_XFAN; ///< "XFan" -const PROGMEM char* kHealthStr = D_STR_HEALTH; ///< "Health" -const PROGMEM char* kModelStr = D_STR_MODEL; ///< "Model" -const PROGMEM char* kTempStr = D_STR_TEMP; ///< "Temp" -const PROGMEM char* kIFeelStr = D_STR_IFEEL; ///< "IFeel" -const PROGMEM char* kHumidStr = D_STR_HUMID; ///< "Humid" -const PROGMEM char* kSaveStr = D_STR_SAVE; ///< "Save" -const PROGMEM char* kEyeStr = D_STR_EYE; ///< "Eye" -const PROGMEM char* kFollowStr = D_STR_FOLLOW; ///< "Follow" -const PROGMEM char* kIonStr = D_STR_ION; ///< "Ion" -const PROGMEM char* kFreshStr = D_STR_FRESH; ///< "Fresh" -const PROGMEM char* kHoldStr = D_STR_HOLD; ///< "Hold" -const PROGMEM char* kButtonStr = D_STR_BUTTON; ///< "Button" -const PROGMEM char* k8CHeatStr = D_STR_8C_HEAT; ///< "8C Heat" -const PROGMEM char* k10CHeatStr = D_STR_10C_HEAT; ///< "10C Heat" -const PROGMEM char* kNightStr = D_STR_NIGHT; ///< "Night" -const PROGMEM char* kSilentStr = D_STR_SILENT; ///< "Silent" -const PROGMEM char* kFilterStr = D_STR_FILTER; ///< "Filter" -const PROGMEM char* k3DStr = D_STR_3D; ///< "3D" -const PROGMEM char* kCelsiusStr = D_STR_CELSIUS; ///< "Celsius" -const PROGMEM char* kCelsiusFahrenheitStr = D_STR_CELSIUS_FAHRENHEIT; ///< +IRTEXT_CONST_STRING(kUnknownStr, D_STR_UNKNOWN); ///< "Unknown" +IRTEXT_CONST_STRING(kProtocolStr, D_STR_PROTOCOL); ///< "Protocol" +IRTEXT_CONST_STRING(kPowerStr, D_STR_POWER); ///< "Power" +IRTEXT_CONST_STRING(kOnStr, D_STR_ON); ///< "On" +IRTEXT_CONST_STRING(kOffStr, D_STR_OFF); ///< "Off" +IRTEXT_CONST_STRING(kModeStr, D_STR_MODE); ///< "Mode" +IRTEXT_CONST_STRING(kToggleStr, D_STR_TOGGLE); ///< "Toggle" +IRTEXT_CONST_STRING(kTurboStr, D_STR_TURBO); ///< "Turbo" +IRTEXT_CONST_STRING(kSuperStr, D_STR_SUPER); ///< "Super" +IRTEXT_CONST_STRING(kSleepStr, D_STR_SLEEP); ///< "Sleep" +IRTEXT_CONST_STRING(kLightStr, D_STR_LIGHT); ///< "Light" +IRTEXT_CONST_STRING(kPowerfulStr, D_STR_POWERFUL); ///< "Powerful" +IRTEXT_CONST_STRING(kQuietStr, D_STR_QUIET); ///< "Quiet" +IRTEXT_CONST_STRING(kEconoStr, D_STR_ECONO); ///< "Econo" +IRTEXT_CONST_STRING(kSwingStr, D_STR_SWING); ///< "Swing" +IRTEXT_CONST_STRING(kSwingHStr, D_STR_SWINGH); ///< "SwingH" +IRTEXT_CONST_STRING(kSwingVStr, D_STR_SWINGV); ///< "SwingV" +IRTEXT_CONST_STRING(kBeepStr, D_STR_BEEP); ///< "Beep" +IRTEXT_CONST_STRING(kZoneFollowStr, D_STR_ZONEFOLLOW); ///< "Zone Follow" +IRTEXT_CONST_STRING(kFixedStr, D_STR_FIXED); ///< "Fixed" +IRTEXT_CONST_STRING(kMouldStr, D_STR_MOULD); ///< "Mould" +IRTEXT_CONST_STRING(kCleanStr, D_STR_CLEAN); ///< "Clean" +IRTEXT_CONST_STRING(kPurifyStr, D_STR_PURIFY); ///< "Purify" +IRTEXT_CONST_STRING(kTimerStr, D_STR_TIMER); ///< "Timer" +IRTEXT_CONST_STRING(kOnTimerStr, D_STR_ONTIMER); ///< "On Timer" +IRTEXT_CONST_STRING(kOffTimerStr, D_STR_OFFTIMER); ///< "Off Timer" +IRTEXT_CONST_STRING(kTimerModeStr, D_STR_TIMERMODE); ///< "Timer Mode" +IRTEXT_CONST_STRING(kClockStr, D_STR_CLOCK); ///< "Clock" +IRTEXT_CONST_STRING(kCommandStr, D_STR_COMMAND); ///< "Command" +IRTEXT_CONST_STRING(kXFanStr, D_STR_XFAN); ///< "XFan" +IRTEXT_CONST_STRING(kHealthStr, D_STR_HEALTH); ///< "Health" +IRTEXT_CONST_STRING(kModelStr, D_STR_MODEL); ///< "Model" +IRTEXT_CONST_STRING(kTempStr, D_STR_TEMP); ///< "Temp" +IRTEXT_CONST_STRING(kIFeelStr, D_STR_IFEEL); ///< "IFeel" +IRTEXT_CONST_STRING(kHumidStr, D_STR_HUMID); ///< "Humid" +IRTEXT_CONST_STRING(kSaveStr, D_STR_SAVE); ///< "Save" +IRTEXT_CONST_STRING(kEyeStr, D_STR_EYE); ///< "Eye" +IRTEXT_CONST_STRING(kFollowStr, D_STR_FOLLOW); ///< "Follow" +IRTEXT_CONST_STRING(kIonStr, D_STR_ION); ///< "Ion" +IRTEXT_CONST_STRING(kFreshStr, D_STR_FRESH); ///< "Fresh" +IRTEXT_CONST_STRING(kHoldStr, D_STR_HOLD); ///< "Hold" +IRTEXT_CONST_STRING(kButtonStr, D_STR_BUTTON); ///< "Button" +IRTEXT_CONST_STRING(k8CHeatStr, D_STR_8C_HEAT); ///< "8C Heat" +IRTEXT_CONST_STRING(k10CHeatStr, D_STR_10C_HEAT); ///< "10C Heat" +IRTEXT_CONST_STRING(kNightStr, D_STR_NIGHT); ///< "Night" +IRTEXT_CONST_STRING(kSilentStr, D_STR_SILENT); ///< "Silent" +IRTEXT_CONST_STRING(kFilterStr, D_STR_FILTER); ///< "Filter" +IRTEXT_CONST_STRING(k3DStr, D_STR_3D); ///< "3D" +IRTEXT_CONST_STRING(kCelsiusStr, D_STR_CELSIUS); ///< "Celsius" +IRTEXT_CONST_STRING(kCelsiusFahrenheitStr, D_STR_CELSIUS_FAHRENHEIT); ///< ///< "Celsius/Fahrenheit" -const PROGMEM char* kTempUpStr = D_STR_TEMPUP; ///< "Temp Up" -const PROGMEM char* kTempDownStr = D_STR_TEMPDOWN; ///< "Temp Down" -const PROGMEM char* kStartStr = D_STR_START; ///< "Start" -const PROGMEM char* kStopStr = D_STR_STOP; ///< "Stop" -const PROGMEM char* kMoveStr = D_STR_MOVE; ///< "Move" -const PROGMEM char* kSetStr = D_STR_SET; ///< "Set" -const PROGMEM char* kCancelStr = D_STR_CANCEL; ///< "Cancel" -const PROGMEM char* kUpStr = D_STR_UP; ///< "Up" -const PROGMEM char* kDownStr = D_STR_DOWN; ///< "Down" -const PROGMEM char* kChangeStr = D_STR_CHANGE; ///< "Change" -const PROGMEM char* kComfortStr = D_STR_COMFORT; ///< "Comfort" -const PROGMEM char* kSensorStr = D_STR_SENSOR; ///< "Sensor" -const PROGMEM char* kWeeklyTimerStr = D_STR_WEEKLYTIMER; ///< "WeeklyTimer" -const PROGMEM char* kWifiStr = D_STR_WIFI; ///< "Wifi" -const PROGMEM char* kLastStr = D_STR_LAST; ///< "Last" -const PROGMEM char* kFastStr = D_STR_FAST; ///< "Fast" -const PROGMEM char* kSlowStr = D_STR_SLOW; ///< "Slow" -const PROGMEM char* kAirFlowStr = D_STR_AIRFLOW; ///< "Air Flow" -const PROGMEM char* kStepStr = D_STR_STEP; ///< "Step" -const PROGMEM char* kNAStr = D_STR_NA; ///< "N/A" -const PROGMEM char* kInsideStr = D_STR_INSIDE; ///< "Inside" -const PROGMEM char* kOutsideStr = D_STR_OUTSIDE; ///< "Outside" -const PROGMEM char* kLoudStr = D_STR_LOUD; ///< "Loud" -const PROGMEM char* kLowerStr = D_STR_LOWER; ///< "Lower" -const PROGMEM char* kUpperStr = D_STR_UPPER; ///< "Upper" -const PROGMEM char* kBreezeStr = D_STR_BREEZE; ///< "Breeze" -const PROGMEM char* kCirculateStr = D_STR_CIRCULATE; ///< "Circulate" -const PROGMEM char* kCeilingStr = D_STR_CEILING; ///< "Ceiling" -const PROGMEM char* kWallStr = D_STR_WALL; ///< "Wall" -const PROGMEM char* kRoomStr = D_STR_ROOM; ///< "Room" -const PROGMEM char* k6thSenseStr = D_STR_6THSENSE; ///< "6th Sense" -const PROGMEM char* kTypeStr = D_STR_TYPE; ///< "Type" -const PROGMEM char* kSpecialStr = D_STR_SPECIAL; ///< "Special" -const PROGMEM char* kIdStr = D_STR_ID; ///< "Id" / Device Identifier -const PROGMEM char* kVaneStr = D_STR_VANE; ///< "Vane" +IRTEXT_CONST_STRING(kTempUpStr, D_STR_TEMPUP); ///< "Temp Up" +IRTEXT_CONST_STRING(kTempDownStr, D_STR_TEMPDOWN); ///< "Temp Down" +IRTEXT_CONST_STRING(kStartStr, D_STR_START); ///< "Start" +IRTEXT_CONST_STRING(kStopStr, D_STR_STOP); ///< "Stop" +IRTEXT_CONST_STRING(kMoveStr, D_STR_MOVE); ///< "Move" +IRTEXT_CONST_STRING(kSetStr, D_STR_SET); ///< "Set" +IRTEXT_CONST_STRING(kCancelStr, D_STR_CANCEL); ///< "Cancel" +IRTEXT_CONST_STRING(kUpStr, D_STR_UP); ///< "Up" +IRTEXT_CONST_STRING(kDownStr, D_STR_DOWN); ///< "Down" +IRTEXT_CONST_STRING(kChangeStr, D_STR_CHANGE); ///< "Change" +IRTEXT_CONST_STRING(kComfortStr, D_STR_COMFORT); ///< "Comfort" +IRTEXT_CONST_STRING(kSensorStr, D_STR_SENSOR); ///< "Sensor" +IRTEXT_CONST_STRING(kWeeklyTimerStr, D_STR_WEEKLYTIMER); ///< "WeeklyTimer" +IRTEXT_CONST_STRING(kWifiStr, D_STR_WIFI); ///< "Wifi" +IRTEXT_CONST_STRING(kLastStr, D_STR_LAST); ///< "Last" +IRTEXT_CONST_STRING(kFastStr, D_STR_FAST); ///< "Fast" +IRTEXT_CONST_STRING(kSlowStr, D_STR_SLOW); ///< "Slow" +IRTEXT_CONST_STRING(kAirFlowStr, D_STR_AIRFLOW); ///< "Air Flow" +IRTEXT_CONST_STRING(kStepStr, D_STR_STEP); ///< "Step" +IRTEXT_CONST_STRING(kNAStr, D_STR_NA); ///< "N/A" +IRTEXT_CONST_STRING(kInsideStr, D_STR_INSIDE); ///< "Inside" +IRTEXT_CONST_STRING(kOutsideStr, D_STR_OUTSIDE); ///< "Outside" +IRTEXT_CONST_STRING(kLoudStr, D_STR_LOUD); ///< "Loud" +IRTEXT_CONST_STRING(kLowerStr, D_STR_LOWER); ///< "Lower" +IRTEXT_CONST_STRING(kUpperStr, D_STR_UPPER); ///< "Upper" +IRTEXT_CONST_STRING(kBreezeStr, D_STR_BREEZE); ///< "Breeze" +IRTEXT_CONST_STRING(kCirculateStr, D_STR_CIRCULATE); ///< "Circulate" +IRTEXT_CONST_STRING(kCeilingStr, D_STR_CEILING); ///< "Ceiling" +IRTEXT_CONST_STRING(kWallStr, D_STR_WALL); ///< "Wall" +IRTEXT_CONST_STRING(kRoomStr, D_STR_ROOM); ///< "Room" +IRTEXT_CONST_STRING(k6thSenseStr, D_STR_6THSENSE); ///< "6th Sense" +IRTEXT_CONST_STRING(kTypeStr, D_STR_TYPE); ///< "Type" +IRTEXT_CONST_STRING(kSpecialStr, D_STR_SPECIAL); ///< "Special" +IRTEXT_CONST_STRING(kIdStr, D_STR_ID); ///< "Id" / Device Identifier +IRTEXT_CONST_STRING(kVaneStr, D_STR_VANE); ///< "Vane" -const PROGMEM char* kAutoStr = D_STR_AUTO; ///< "Auto" -const PROGMEM char* kAutomaticStr = D_STR_AUTOMATIC; ///< "Automatic" -const PROGMEM char* kManualStr = D_STR_MANUAL; ///< "Manual" -const PROGMEM char* kCoolStr = D_STR_COOL; ///< "Cool" -const PROGMEM char* kHeatStr = D_STR_HEAT; ///< "Heat" -const PROGMEM char* kDryStr = D_STR_DRY; ///< "Dry" -const PROGMEM char* kFanStr = D_STR_FAN; ///< "Fan" +IRTEXT_CONST_STRING(kAutoStr, D_STR_AUTO); ///< "Auto" +IRTEXT_CONST_STRING(kAutomaticStr, D_STR_AUTOMATIC); ///< "Automatic" +IRTEXT_CONST_STRING(kManualStr, D_STR_MANUAL); ///< "Manual" +IRTEXT_CONST_STRING(kCoolStr, D_STR_COOL); ///< "Cool" +IRTEXT_CONST_STRING(kHeatStr, D_STR_HEAT); ///< "Heat" +IRTEXT_CONST_STRING(kDryStr, D_STR_DRY); ///< "Dry" +IRTEXT_CONST_STRING(kFanStr, D_STR_FAN); ///< "Fan" // The following Fans strings with "only" are required to help with // HomeAssistant & Google Home Climate integration. For compatibility only. // Ref: https://www.home-assistant.io/integrations/google_assistant/#climate-operation-modes -const PROGMEM char* kFanOnlyStr = D_STR_FANONLY; ///< "fan-only" -const PROGMEM char* kFan_OnlyStr = D_STR_FAN_ONLY; ///< "fan_only" (legacy use) -const PROGMEM char* kFanOnlyWithSpaceStr = D_STR_FANSPACEONLY; ///< "Fan Only" -const PROGMEM char* kFanOnlyNoSpaceStr = D_STR_FANONLYNOSPACE; ///< "FanOnly" +IRTEXT_CONST_STRING(kFanOnlyStr, D_STR_FANONLY); ///< "fan-only" +IRTEXT_CONST_STRING(kFan_OnlyStr, D_STR_FAN_ONLY); ///< "fan_only" (legacy) +IRTEXT_CONST_STRING(kFanOnlyWithSpaceStr, D_STR_FANSPACEONLY); ///< "Fan Only" +IRTEXT_CONST_STRING(kFanOnlyNoSpaceStr, D_STR_FANONLYNOSPACE); ///< "FanOnly" -const PROGMEM char* kRecycleStr = D_STR_RECYCLE; ///< "Recycle" +IRTEXT_CONST_STRING(kRecycleStr, D_STR_RECYCLE); ///< "Recycle" -const PROGMEM char* kMaxStr = D_STR_MAX; ///< "Max" -const PROGMEM char* kMaximumStr = D_STR_MAXIMUM; ///< "Maximum" -const PROGMEM char* kMinStr = D_STR_MIN; ///< "Min" -const PROGMEM char* kMinimumStr = D_STR_MINIMUM; ///< "Minimum" -const PROGMEM char* kMedStr = D_STR_MED; ///< "Med" -const PROGMEM char* kMediumStr = D_STR_MEDIUM; ///< "Medium" +IRTEXT_CONST_STRING(kMaxStr, D_STR_MAX); ///< "Max" +IRTEXT_CONST_STRING(kMaximumStr, D_STR_MAXIMUM); ///< "Maximum" +IRTEXT_CONST_STRING(kMinStr, D_STR_MIN); ///< "Min" +IRTEXT_CONST_STRING(kMinimumStr, D_STR_MINIMUM); ///< "Minimum" +IRTEXT_CONST_STRING(kMedStr, D_STR_MED); ///< "Med" +IRTEXT_CONST_STRING(kMediumStr, D_STR_MEDIUM); ///< "Medium" -const PROGMEM char* kHighestStr = D_STR_HIGHEST; ///< "Highest" -const PROGMEM char* kHighStr = D_STR_HIGH; ///< "High" -const PROGMEM char* kHiStr = D_STR_HI; ///< "Hi" -const PROGMEM char* kMidStr = D_STR_MID; ///< "Mid" -const PROGMEM char* kMiddleStr = D_STR_MIDDLE; ///< "Middle" -const PROGMEM char* kLowStr = D_STR_LOW; ///< "Low" -const PROGMEM char* kLoStr = D_STR_LO; ///< "Lo" -const PROGMEM char* kLowestStr = D_STR_LOWEST; ///< "Lowest" -const PROGMEM char* kMaxRightStr = D_STR_MAXRIGHT; ///< "Max Right" -const PROGMEM char* kRightMaxStr = D_STR_RIGHTMAX_NOSPACE; ///< "RightMax" -const PROGMEM char* kRightStr = D_STR_RIGHT; ///< "Right" -const PROGMEM char* kLeftStr = D_STR_LEFT; ///< "Left" -const PROGMEM char* kMaxLeftStr = D_STR_MAXLEFT; ///< "Max Left" -const PROGMEM char* kLeftMaxStr = D_STR_LEFTMAX_NOSPACE; ///< "LeftMax" -const PROGMEM char* kWideStr = D_STR_WIDE; ///< "Wide" -const PROGMEM char* kCentreStr = D_STR_CENTRE; ///< "Centre" -const PROGMEM char* kTopStr = D_STR_TOP; ///< "Top" -const PROGMEM char* kBottomStr = D_STR_BOTTOM; ///< "Bottom" +IRTEXT_CONST_STRING(kHighestStr, D_STR_HIGHEST); ///< "Highest" +IRTEXT_CONST_STRING(kHighStr, D_STR_HIGH); ///< "High" +IRTEXT_CONST_STRING(kHiStr, D_STR_HI); ///< "Hi" +IRTEXT_CONST_STRING(kMidStr, D_STR_MID); ///< "Mid" +IRTEXT_CONST_STRING(kMiddleStr, D_STR_MIDDLE); ///< "Middle" +IRTEXT_CONST_STRING(kLowStr, D_STR_LOW); ///< "Low" +IRTEXT_CONST_STRING(kLoStr, D_STR_LO); ///< "Lo" +IRTEXT_CONST_STRING(kLowestStr, D_STR_LOWEST); ///< "Lowest" +IRTEXT_CONST_STRING(kMaxRightStr, D_STR_MAXRIGHT); ///< "Max Right" +IRTEXT_CONST_STRING(kRightMaxStr, D_STR_RIGHTMAX_NOSPACE); ///< "RightMax" +IRTEXT_CONST_STRING(kRightStr, D_STR_RIGHT); ///< "Right" +IRTEXT_CONST_STRING(kLeftStr, D_STR_LEFT); ///< "Left" +IRTEXT_CONST_STRING(kMaxLeftStr, D_STR_MAXLEFT); ///< "Max Left" +IRTEXT_CONST_STRING(kLeftMaxStr, D_STR_LEFTMAX_NOSPACE); ///< "LeftMax" +IRTEXT_CONST_STRING(kWideStr, D_STR_WIDE); ///< "Wide" +IRTEXT_CONST_STRING(kCentreStr, D_STR_CENTRE); ///< "Centre" +IRTEXT_CONST_STRING(kTopStr, D_STR_TOP); ///< "Top" +IRTEXT_CONST_STRING(kBottomStr, D_STR_BOTTOM); ///< "Bottom" // Compound words/phrases/descriptions from pre-defined words. -const PROGMEM char* kEconoToggleStr = D_STR_ECONOTOGGLE; ///< "Econo Toggle" -const PROGMEM char* kEyeAutoStr = D_STR_EYEAUTO; ///< "Eye Auto" -const PROGMEM char* kLightToggleStr = D_STR_LIGHTTOGGLE; ///< "Light Toggle" -const PROGMEM char* kOutsideQuietStr = D_STR_OUTSIDEQUIET; ///< "Outside Quiet" -const PROGMEM char* kPowerToggleStr = D_STR_POWERTOGGLE; ///< "Power Toggle" -const PROGMEM char* kPowerButtonStr = D_STR_POWERBUTTON; ///< "Power Button" -const PROGMEM char* kPreviousPowerStr = D_STR_PREVIOUSPOWER; ///< +IRTEXT_CONST_STRING(kEconoToggleStr, D_STR_ECONOTOGGLE); ///< "Econo Toggle" +IRTEXT_CONST_STRING(kEyeAutoStr, D_STR_EYEAUTO); ///< "Eye Auto" +IRTEXT_CONST_STRING(kLightToggleStr, D_STR_LIGHTTOGGLE); ///< "Light Toggle" +///< "Outside Quiet" +IRTEXT_CONST_STRING(kOutsideQuietStr, D_STR_OUTSIDEQUIET); +IRTEXT_CONST_STRING(kPowerToggleStr, D_STR_POWERTOGGLE); ///< "Power Toggle" +IRTEXT_CONST_STRING(kPowerButtonStr, D_STR_POWERBUTTON); ///< "Power Button" +IRTEXT_CONST_STRING(kPreviousPowerStr, D_STR_PREVIOUSPOWER); ///< ///< "Previous Power" -const PROGMEM char* kDisplayTempStr = D_STR_DISPLAYTEMP; ///< "Display Temp" -const PROGMEM char* kSensorTempStr = D_STR_SENSORTEMP; ///< "Sensor Temp" -const PROGMEM char* kSleepTimerStr = D_STR_SLEEP_TIMER; ///< "Sleep Timer" -const PROGMEM char* kSwingVModeStr = D_STR_SWINGVMODE; ///< "Swing(V) Mode" -const PROGMEM char* kSwingVToggleStr = D_STR_SWINGVTOGGLE; ///< +IRTEXT_CONST_STRING(kDisplayTempStr, D_STR_DISPLAYTEMP); ///< "Display Temp" +IRTEXT_CONST_STRING(kSensorTempStr, D_STR_SENSORTEMP); ///< "Sensor Temp" +IRTEXT_CONST_STRING(kSleepTimerStr, D_STR_SLEEP_TIMER); ///< "Sleep Timer" +IRTEXT_CONST_STRING(kSwingVModeStr, D_STR_SWINGVMODE); ///< "Swing(V) Mode" +IRTEXT_CONST_STRING(kSwingVToggleStr, D_STR_SWINGVTOGGLE); ///< ///< "Swing(V) Toggle" -const PROGMEM char* kTurboToggleStr = D_STR_TURBOTOGGLE; ///< "Turbo Toggle" +IRTEXT_CONST_STRING(kTurboToggleStr, D_STR_TURBOTOGGLE); ///< "Turbo Toggle" // Separators -char kTimeSep = D_CHR_TIME_SEP; ///< ':' -const PROGMEM char* kSpaceLBraceStr = D_STR_SPACELBRACE; ///< " (" -const PROGMEM char* kCommaSpaceStr = D_STR_COMMASPACE; ///< ", " -const PROGMEM char* kColonSpaceStr = D_STR_COLONSPACE; ///< ": " +const char kTimeSep = D_CHR_TIME_SEP; ///< ':' +IRTEXT_CONST_STRING(kSpaceLBraceStr, D_STR_SPACELBRACE); ///< " (" +IRTEXT_CONST_STRING(kCommaSpaceStr, D_STR_COMMASPACE); ///< ", " +IRTEXT_CONST_STRING(kColonSpaceStr, D_STR_COLONSPACE); ///< ": " // IRutils // - Time -const PROGMEM char* kDayStr = D_STR_DAY; ///< "Day" -const PROGMEM char* kDaysStr = D_STR_DAYS; ///< "Days" -const PROGMEM char* kHourStr = D_STR_HOUR; ///< "Hour" -const PROGMEM char* kHoursStr = D_STR_HOURS; ///< "Hours" -const PROGMEM char* kMinuteStr = D_STR_MINUTE; ///< "Minute" -const PROGMEM char* kMinutesStr = D_STR_MINUTES; ///< "Minutes" -const PROGMEM char* kSecondStr = D_STR_SECOND; ///< "Second" -const PROGMEM char* kSecondsStr = D_STR_SECONDS; ///< "Seconds" -const PROGMEM char* kNowStr = D_STR_NOW; ///< "Now" -const PROGMEM char* kThreeLetterDayOfWeekStr = D_STR_THREELETTERDAYS; ///< +IRTEXT_CONST_STRING(kDayStr, D_STR_DAY); ///< "Day" +IRTEXT_CONST_STRING(kDaysStr, D_STR_DAYS); ///< "Days" +IRTEXT_CONST_STRING(kHourStr, D_STR_HOUR); ///< "Hour" +IRTEXT_CONST_STRING(kHoursStr, D_STR_HOURS); ///< "Hours" +IRTEXT_CONST_STRING(kMinuteStr, D_STR_MINUTE); ///< "Minute" +IRTEXT_CONST_STRING(kMinutesStr, D_STR_MINUTES); ///< "Minutes" +IRTEXT_CONST_STRING(kSecondStr, D_STR_SECOND); ///< "Second" +IRTEXT_CONST_STRING(kSecondsStr, D_STR_SECONDS); ///< "Seconds" +IRTEXT_CONST_STRING(kNowStr, D_STR_NOW); ///< "Now" +IRTEXT_CONST_STRING(kThreeLetterDayOfWeekStr, D_STR_THREELETTERDAYS); ///< ///< "SunMonTueWedThuFriSat" -const PROGMEM char* kYesStr = D_STR_YES; ///< "Yes" -const PROGMEM char* kNoStr = D_STR_NO; ///< "No" -const PROGMEM char* kTrueStr = D_STR_TRUE; ///< "True" -const PROGMEM char* kFalseStr = D_STR_FALSE; ///< "False" +IRTEXT_CONST_STRING(kYesStr, D_STR_YES); ///< "Yes" +IRTEXT_CONST_STRING(kNoStr, D_STR_NO); ///< "No" +IRTEXT_CONST_STRING(kTrueStr, D_STR_TRUE); ///< "True" +IRTEXT_CONST_STRING(kFalseStr, D_STR_FALSE); ///< "False" -const PROGMEM char* kRepeatStr = D_STR_REPEAT; ///< "Repeat" -const PROGMEM char* kCodeStr = D_STR_CODE; ///< "Code" -const PROGMEM char* kBitsStr = D_STR_BITS; ///< "Bits" +IRTEXT_CONST_STRING(kRepeatStr, D_STR_REPEAT); ///< "Repeat" +IRTEXT_CONST_STRING(kCodeStr, D_STR_CODE); ///< "Code" +IRTEXT_CONST_STRING(kBitsStr, D_STR_BITS); ///< "Bits" // Protocol Names // Needs to be in decode_type_t order. -const PROGMEM char *kAllProtocolNamesStr = +IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) { D_STR_UNUSED "\x0" D_STR_RC5 "\x0" D_STR_RC6 "\x0" @@ -302,4 +323,7 @@ const PROGMEM char *kAllProtocolNamesStr = D_STR_BOSE "\x0" D_STR_ARRIS "\x0" ///< New protocol strings should be added just above this line. - "\x0"; ///< This string requires double null termination. + "\x0" ///< This string requires double null termination. +}; + +IRTEXT_CONST_BLOB_PTR(kAllProtocolNamesStr); diff --git a/src/IRtext.h b/src/IRtext.h index 20d1a958a..589cd38ef 100644 --- a/src/IRtext.h +++ b/src/IRtext.h @@ -12,161 +12,171 @@ // Constant text to be shared across all object files. // This means there is only one copy of the character/string/text etc. -extern char kTimeSep; -extern const char* k10CHeatStr; -extern const char* k3DStr; -extern const char* k6thSenseStr; -extern const char* k8CHeatStr; -extern const char* kAirFlowStr; -extern const char *kAllProtocolNamesStr; -extern const char* kAutomaticStr; -extern const char* kAutoStr; -extern const char* kBeepStr; -extern const char* kBitsStr; -extern const char* kBottomStr; -extern const char* kBreezeStr; -extern const char* kButtonStr; -extern const char* kCancelStr; -extern const char* kCeilingStr; -extern const char* kCelsiusFahrenheitStr; -extern const char* kCelsiusStr; -extern const char* kCentreStr; -extern const char* kChangeStr; -extern const char* kCirculateStr; -extern const char* kCleanStr; -extern const char* kClockStr; -extern const char* kCodeStr; -extern const char* kColonSpaceStr; -extern const char* kComfortStr; -extern const char* kCommandStr; -extern const char* kCommaSpaceStr; -extern const char* kCoolStr; -extern const char* kDaysStr; -extern const char* kDayStr; -extern const char* kDisplayTempStr; -extern const char* kDownStr; -extern const char* kDryStr; -extern const char* kEconoStr; -extern const char* kEconoToggleStr; -extern const char* kEyeAutoStr; -extern const char* kEyeStr; -extern const char* kFalseStr; -extern const char* kFanOnlyNoSpaceStr; -extern const char* kFan_OnlyStr; -extern const char* kFanOnlyStr; -extern const char* kFanOnlyWithSpaceStr; -extern const char* kFanStr; -extern const char* kFastStr; -extern const char* kFilterStr; -extern const char* kFixedStr; -extern const char* kFollowStr; -extern const char* kFreshStr; -extern const char* kHealthStr; -extern const char* kHeatStr; -extern const char* kHighestStr; -extern const char* kHighStr; -extern const char* kHiStr; -extern const char* kHoldStr; -extern const char* kHoursStr; -extern const char* kHourStr; -extern const char* kHumidStr; -extern const char* kIdStr; -extern const char* kIFeelStr; -extern const char* kInsideStr; -extern const char* kIonStr; -extern const char* kLastStr; -extern const char* kLeftMaxStr; -extern const char* kLeftStr; -extern const char* kLightStr; -extern const char* kLightToggleStr; -extern const char* kLoStr; -extern const char* kLoudStr; -extern const char* kLowerStr; -extern const char* kLowestStr; -extern const char* kLowStr; -extern const char* kManualStr; -extern const char* kMaximumStr; -extern const char* kMaxLeftStr; -extern const char* kMaxRightStr; -extern const char* kMaxStr; -extern const char* kMediumStr; -extern const char* kMedStr; -extern const char* kMiddleStr; -extern const char* kMidStr; -extern const char* kMinimumStr; -extern const char* kMinStr; -extern const char* kMinutesStr; -extern const char* kMinuteStr; -extern const char* kModelStr; -extern const char* kModeStr; -extern const char* kMouldStr; -extern const char* kMoveStr; -extern const char* kNAStr; -extern const char* kNightStr; -extern const char* kNoStr; -extern const char* kNowStr; -extern const char* kOffStr; -extern const char* kOffTimerStr; -extern const char* kOnStr; -extern const char* kOnTimerStr; -extern const char* kOutsideQuietStr; -extern const char* kOutsideStr; -extern const char* kPowerButtonStr; -extern const char* kPowerfulStr; -extern const char* kPowerStr; -extern const char* kPowerToggleStr; -extern const char* kPreviousPowerStr; -extern const char* kProtocolStr; -extern const char* kPurifyStr; -extern const char* kQuietStr; -extern const char* kRecycleStr; -extern const char* kRepeatStr; -extern const char* kRightMaxStr; -extern const char* kRightStr; -extern const char* kRoomStr; -extern const char* kSaveStr; -extern const char* kSecondsStr; -extern const char* kSecondStr; -extern const char* kSensorStr; -extern const char* kSensorTempStr; -extern const char* kSetStr; -extern const char* kSilentStr; -extern const char* kSleepStr; -extern const char* kSleepTimerStr; -extern const char* kSlowStr; -extern const char* kSpaceLBraceStr; -extern const char* kSpecialStr; -extern const char* kStartStr; -extern const char* kStepStr; -extern const char* kStopStr; -extern const char* kSuperStr; -extern const char* kSwingHStr; -extern const char* kSwingStr; -extern const char* kSwingVModeStr; -extern const char* kSwingVStr; -extern const char* kSwingVToggleStr; -extern const char* kTempDownStr; -extern const char* kTempStr; -extern const char* kTempUpStr; -extern const char* kThreeLetterDayOfWeekStr; -extern const char* kTimerModeStr; -extern const char* kTimerStr; -extern const char* kToggleStr; -extern const char* kTopStr; -extern const char* kTrueStr; -extern const char* kTurboStr; -extern const char* kTurboToggleStr; -extern const char* kTypeStr; -extern const char* kUnknownStr; -extern const char* kUpperStr; -extern const char* kUpStr; -extern const char* kVaneStr; -extern const char* kWallStr; -extern const char* kWeeklyTimerStr; -extern const char* kWideStr; -extern const char* kWifiStr; -extern const char* kXFanStr; -extern const char* kYesStr; -extern const char* kZoneFollowStr; +#ifdef ESP8266 +class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\ + reinterpret_cast<const __FlashStringHelper*>(PTR) +#define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME +#else // ESP8266 +#define IRTEXT_CONST_PTR_CAST(PTR) PTR +#define IRTEXT_CONST_PTR(NAME) const char* const NAME +#endif // ESP8266 + +extern const char kTimeSep; +extern IRTEXT_CONST_PTR(k10CHeatStr); +extern IRTEXT_CONST_PTR(k3DStr); +extern IRTEXT_CONST_PTR(k6thSenseStr); +extern IRTEXT_CONST_PTR(k8CHeatStr); +extern IRTEXT_CONST_PTR(kAirFlowStr); +extern IRTEXT_CONST_PTR(kAutomaticStr); +extern IRTEXT_CONST_PTR(kAutoStr); +extern IRTEXT_CONST_PTR(kBeepStr); +extern IRTEXT_CONST_PTR(kBitsStr); +extern IRTEXT_CONST_PTR(kBottomStr); +extern IRTEXT_CONST_PTR(kBreezeStr); +extern IRTEXT_CONST_PTR(kButtonStr); +extern IRTEXT_CONST_PTR(kCancelStr); +extern IRTEXT_CONST_PTR(kCeilingStr); +extern IRTEXT_CONST_PTR(kCelsiusFahrenheitStr); +extern IRTEXT_CONST_PTR(kCelsiusStr); +extern IRTEXT_CONST_PTR(kCentreStr); +extern IRTEXT_CONST_PTR(kChangeStr); +extern IRTEXT_CONST_PTR(kCirculateStr); +extern IRTEXT_CONST_PTR(kCleanStr); +extern IRTEXT_CONST_PTR(kClockStr); +extern IRTEXT_CONST_PTR(kCodeStr); +extern IRTEXT_CONST_PTR(kColonSpaceStr); +extern IRTEXT_CONST_PTR(kComfortStr); +extern IRTEXT_CONST_PTR(kCommandStr); +extern IRTEXT_CONST_PTR(kCommaSpaceStr); +extern IRTEXT_CONST_PTR(kCoolStr); +extern IRTEXT_CONST_PTR(kDaysStr); +extern IRTEXT_CONST_PTR(kDayStr); +extern IRTEXT_CONST_PTR(kDisplayTempStr); +extern IRTEXT_CONST_PTR(kDownStr); +extern IRTEXT_CONST_PTR(kDryStr); +extern IRTEXT_CONST_PTR(kEconoStr); +extern IRTEXT_CONST_PTR(kEconoToggleStr); +extern IRTEXT_CONST_PTR(kEyeAutoStr); +extern IRTEXT_CONST_PTR(kEyeStr); +extern IRTEXT_CONST_PTR(kFalseStr); +extern IRTEXT_CONST_PTR(kFanOnlyNoSpaceStr); +extern IRTEXT_CONST_PTR(kFan_OnlyStr); +extern IRTEXT_CONST_PTR(kFanOnlyStr); +extern IRTEXT_CONST_PTR(kFanOnlyWithSpaceStr); +extern IRTEXT_CONST_PTR(kFanStr); +extern IRTEXT_CONST_PTR(kFastStr); +extern IRTEXT_CONST_PTR(kFilterStr); +extern IRTEXT_CONST_PTR(kFixedStr); +extern IRTEXT_CONST_PTR(kFollowStr); +extern IRTEXT_CONST_PTR(kFreshStr); +extern IRTEXT_CONST_PTR(kHealthStr); +extern IRTEXT_CONST_PTR(kHeatStr); +extern IRTEXT_CONST_PTR(kHighestStr); +extern IRTEXT_CONST_PTR(kHighStr); +extern IRTEXT_CONST_PTR(kHiStr); +extern IRTEXT_CONST_PTR(kHoldStr); +extern IRTEXT_CONST_PTR(kHoursStr); +extern IRTEXT_CONST_PTR(kHourStr); +extern IRTEXT_CONST_PTR(kHumidStr); +extern IRTEXT_CONST_PTR(kIdStr); +extern IRTEXT_CONST_PTR(kIFeelStr); +extern IRTEXT_CONST_PTR(kInsideStr); +extern IRTEXT_CONST_PTR(kIonStr); +extern IRTEXT_CONST_PTR(kLastStr); +extern IRTEXT_CONST_PTR(kLeftMaxStr); +extern IRTEXT_CONST_PTR(kLeftStr); +extern IRTEXT_CONST_PTR(kLightStr); +extern IRTEXT_CONST_PTR(kLightToggleStr); +extern IRTEXT_CONST_PTR(kLoStr); +extern IRTEXT_CONST_PTR(kLoudStr); +extern IRTEXT_CONST_PTR(kLowerStr); +extern IRTEXT_CONST_PTR(kLowestStr); +extern IRTEXT_CONST_PTR(kLowStr); +extern IRTEXT_CONST_PTR(kManualStr); +extern IRTEXT_CONST_PTR(kMaximumStr); +extern IRTEXT_CONST_PTR(kMaxLeftStr); +extern IRTEXT_CONST_PTR(kMaxRightStr); +extern IRTEXT_CONST_PTR(kMaxStr); +extern IRTEXT_CONST_PTR(kMediumStr); +extern IRTEXT_CONST_PTR(kMedStr); +extern IRTEXT_CONST_PTR(kMiddleStr); +extern IRTEXT_CONST_PTR(kMidStr); +extern IRTEXT_CONST_PTR(kMinimumStr); +extern IRTEXT_CONST_PTR(kMinStr); +extern IRTEXT_CONST_PTR(kMinutesStr); +extern IRTEXT_CONST_PTR(kMinuteStr); +extern IRTEXT_CONST_PTR(kModelStr); +extern IRTEXT_CONST_PTR(kModeStr); +extern IRTEXT_CONST_PTR(kMouldStr); +extern IRTEXT_CONST_PTR(kMoveStr); +extern IRTEXT_CONST_PTR(kNAStr); +extern IRTEXT_CONST_PTR(kNightStr); +extern IRTEXT_CONST_PTR(kNoStr); +extern IRTEXT_CONST_PTR(kNowStr); +extern IRTEXT_CONST_PTR(kOffStr); +extern IRTEXT_CONST_PTR(kOffTimerStr); +extern IRTEXT_CONST_PTR(kOnStr); +extern IRTEXT_CONST_PTR(kOnTimerStr); +extern IRTEXT_CONST_PTR(kOutsideQuietStr); +extern IRTEXT_CONST_PTR(kOutsideStr); +extern IRTEXT_CONST_PTR(kPowerButtonStr); +extern IRTEXT_CONST_PTR(kPowerfulStr); +extern IRTEXT_CONST_PTR(kPowerStr); +extern IRTEXT_CONST_PTR(kPowerToggleStr); +extern IRTEXT_CONST_PTR(kPreviousPowerStr); +extern IRTEXT_CONST_PTR(kProtocolStr); +extern IRTEXT_CONST_PTR(kPurifyStr); +extern IRTEXT_CONST_PTR(kQuietStr); +extern IRTEXT_CONST_PTR(kRecycleStr); +extern IRTEXT_CONST_PTR(kRepeatStr); +extern IRTEXT_CONST_PTR(kRightMaxStr); +extern IRTEXT_CONST_PTR(kRightStr); +extern IRTEXT_CONST_PTR(kRoomStr); +extern IRTEXT_CONST_PTR(kSaveStr); +extern IRTEXT_CONST_PTR(kSecondsStr); +extern IRTEXT_CONST_PTR(kSecondStr); +extern IRTEXT_CONST_PTR(kSensorStr); +extern IRTEXT_CONST_PTR(kSensorTempStr); +extern IRTEXT_CONST_PTR(kSetStr); +extern IRTEXT_CONST_PTR(kSilentStr); +extern IRTEXT_CONST_PTR(kSleepStr); +extern IRTEXT_CONST_PTR(kSleepTimerStr); +extern IRTEXT_CONST_PTR(kSlowStr); +extern IRTEXT_CONST_PTR(kSpaceLBraceStr); +extern IRTEXT_CONST_PTR(kSpecialStr); +extern IRTEXT_CONST_PTR(kStartStr); +extern IRTEXT_CONST_PTR(kStepStr); +extern IRTEXT_CONST_PTR(kStopStr); +extern IRTEXT_CONST_PTR(kSuperStr); +extern IRTEXT_CONST_PTR(kSwingHStr); +extern IRTEXT_CONST_PTR(kSwingStr); +extern IRTEXT_CONST_PTR(kSwingVModeStr); +extern IRTEXT_CONST_PTR(kSwingVStr); +extern IRTEXT_CONST_PTR(kSwingVToggleStr); +extern IRTEXT_CONST_PTR(kTempDownStr); +extern IRTEXT_CONST_PTR(kTempStr); +extern IRTEXT_CONST_PTR(kTempUpStr); +extern IRTEXT_CONST_PTR(kThreeLetterDayOfWeekStr); +extern IRTEXT_CONST_PTR(kTimerModeStr); +extern IRTEXT_CONST_PTR(kTimerStr); +extern IRTEXT_CONST_PTR(kToggleStr); +extern IRTEXT_CONST_PTR(kTopStr); +extern IRTEXT_CONST_PTR(kTrueStr); +extern IRTEXT_CONST_PTR(kTurboStr); +extern IRTEXT_CONST_PTR(kTurboToggleStr); +extern IRTEXT_CONST_PTR(kTypeStr); +extern IRTEXT_CONST_PTR(kUnknownStr); +extern IRTEXT_CONST_PTR(kUpperStr); +extern IRTEXT_CONST_PTR(kUpStr); +extern IRTEXT_CONST_PTR(kVaneStr); +extern IRTEXT_CONST_PTR(kWallStr); +extern IRTEXT_CONST_PTR(kWeeklyTimerStr); +extern IRTEXT_CONST_PTR(kWideStr); +extern IRTEXT_CONST_PTR(kWifiStr); +extern IRTEXT_CONST_PTR(kXFanStr); +extern IRTEXT_CONST_PTR(kYesStr); +extern IRTEXT_CONST_PTR(kZoneFollowStr); +extern IRTEXT_CONST_PTR(kAllProtocolNamesStr); #endif // IRTEXT_H_ diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 905f0a04c..4154f7290 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -1,4 +1,4 @@ -// Copyright 2017 David Conran +// Copyright 2017-2021 David Conran #include "IRutils.h" #ifndef UNIT_TEST @@ -17,6 +17,27 @@ #include "IRsend.h" #include "IRtext.h" +// On the ESP8266 platform we need to use a set of ..._P functions +// to handle the strings stored in the flash address space. +#ifndef STRCASECMP +#if defined(ESP8266) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast<const char*>(RHS)) +#else // ESP8266 +#define STRCASECMP strcasecmp +#endif // ESP8266 +#endif // STRCASECMP +#ifndef STRLEN +#if defined(ESP8266) +#define STRLEN(PTR) strlen_P(PTR) +#else // ESP8266 +#define STRLEN(PTR) strlen(PTR) +#endif // ESP8266 +#endif // STRLEN +#ifndef FPSTR +#define FPSTR(X) X +#endif // FPSTR + /// Reverse the order of the requested least significant nr. of bits. /// @param[in] input Bit pattern/integer to reverse. /// @param[in] nbits Nr. of bits to reverse. (LSB -> MSB) @@ -93,21 +114,20 @@ void serialPrintUint64(uint64_t input, uint8_t base) { /// @param[in] str A C-style string containing a protocol name or number. /// @return A decode_type_t enum. (decode_type_t::UNKNOWN if no match.) decode_type_t strToDecodeType(const char * const str) { - const char *ptr = kAllProtocolNamesStr; - uint16_t length = strlen(ptr); + auto *ptr = reinterpret_cast<const char*>(kAllProtocolNamesStr); + uint16_t length = STRLEN(ptr); for (uint16_t i = 0; length; i++) { - if (!strcasecmp(str, ptr)) return (decode_type_t)i; + if (!STRCASECMP(str, ptr)) return (decode_type_t)i; ptr += length + 1; - length = strlen(ptr); + length = STRLEN(ptr); } - // Handle integer values of the type by converting to a string and back again. decode_type_t result = strToDecodeType( typeToString((decode_type_t)atoi(str)).c_str()); if (result > 0) return result; - else - return decode_type_t::UNKNOWN; + + return decode_type_t::UNKNOWN; } /// Convert a protocol type (enum etc) to a human readable string. @@ -117,16 +137,20 @@ decode_type_t strToDecodeType(const char * const str) { String typeToString(const decode_type_t protocol, const bool isRepeat) { String result = ""; result.reserve(30); // Size of longest protocol name + " (Repeat)" - const char *ptr = kAllProtocolNamesStr; if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { result = kUnknownStr; } else { - for (uint16_t i = 0; i <= protocol && strlen(ptr); i++) { - if (i == protocol) { - result = ptr; - break; + auto *ptr = reinterpret_cast<const char*>(kAllProtocolNamesStr); + if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { + result = kUnknownStr; + } else { + for (uint16_t i = 0; i <= protocol && STRLEN(ptr); i++) { + if (i == protocol) { + result = FPSTR(ptr); + break; + } + ptr += STRLEN(ptr) + 1; } - ptr += strlen(ptr) + 1; } } if (isRepeat) { diff --git a/src/ir_Electra.cpp b/src/ir_Electra.cpp index fd70e4bd6..864ab82d6 100644 --- a/src/ir_Electra.cpp +++ b/src/ir_Electra.cpp @@ -351,7 +351,8 @@ String IRElectraAc::toString(void) const { kElectraAcFanMed); result += addBoolToString(getSwingV(), kSwingVStr); result += addBoolToString(getSwingH(), kSwingHStr); - result += addLabeledString(getLightToggle() ? kToggleStr : "-", kLightStr); + result += addLabeledString(getLightToggle() ? String(kToggleStr) + : String("-"), kLightStr); result += addBoolToString(_.Clean, kCleanStr); result += addBoolToString(_.Turbo, kTurboStr); return result; diff --git a/src/ir_Goodweather.cpp b/src/ir_Goodweather.cpp index c86797ad5..2ddcb2aa2 100644 --- a/src/ir_Goodweather.cpp +++ b/src/ir_Goodweather.cpp @@ -346,9 +346,13 @@ String IRGoodweatherAc::toString(void) const { result += addFanToString(_.Fan, kGoodweatherFanHigh, kGoodweatherFanLow, kGoodweatherFanAuto, kGoodweatherFanAuto, kGoodweatherFanMed); - result += addLabeledString(_.Turbo ? kToggleStr : "-", kTurboStr); - result += addLabeledString(_.Light ? kToggleStr : "-", kLightStr); - result += addLabeledString(_.Sleep ? kToggleStr : "-", kSleepStr); + + result += addLabeledString(_.Turbo ? String(kToggleStr) + : String("-"), kTurboStr); + result += addLabeledString(_.Light ? String(kToggleStr) + : String("-"), kLightStr); + result += addLabeledString(_.Sleep ? String(kToggleStr) + : String("-"), kSleepStr); result += addIntToString(_.Swing, kSwingStr); result += kSpaceLBraceStr; switch (_.Swing) { diff --git a/src/ir_Sharp.cpp b/src/ir_Sharp.cpp index 77d282d4a..29be0dee3 100644 --- a/src/ir_Sharp.cpp +++ b/src/ir_Sharp.cpp @@ -870,8 +870,9 @@ String IRSharpAc::toString(void) const { result.reserve(170); // Reserve some heap for the string to reduce fragging. result += addModelToString(decode_type_t::SHARP_AC, getModel(), false); - result += addLabeledString(isPowerSpecial() ? "-" - : (getPower() ? kOnStr : kOffStr), + result += addLabeledString(isPowerSpecial() ? String("-") + : String(getPower() ? kOnStr + : kOffStr), kPowerStr); const uint8_t mode = _.Mode; result += addModeToString( @@ -919,11 +920,13 @@ String IRSharpAc::toString(void) const { switch (model) { case sharp_ac_remote_model_t::A705: case sharp_ac_remote_model_t::A903: - result += addLabeledString(getLightToggle() ? kToggleStr : "-", + result += addLabeledString(getLightToggle() ? String(kToggleStr) + : String("-"), kLightStr); break; default: - result += addLabeledString(getEconoToggle() ? kToggleStr : "-", + result += addLabeledString(getEconoToggle() ? String(kToggleStr) + : String("-"), kEconoStr); } result += addBoolToString(_.Clean, kCleanStr); diff --git a/tools/generate_irtext_h.sh b/tools/generate_irtext_h.sh index df2baee06..b0d9855c4 100755 --- a/tools/generate_irtext_h.sh +++ b/tools/generate_irtext_h.sh @@ -24,12 +24,26 @@ cat >${OUTPUT} << EOF // Constant text to be shared across all object files. // This means there is only one copy of the character/string/text etc. +#ifdef ESP8266 +class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\\ + reinterpret_cast<const __FlashStringHelper*>(PTR) +#define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME +#else // ESP8266 +#define IRTEXT_CONST_PTR_CAST(PTR) PTR +#define IRTEXT_CONST_PTR(NAME) const char* const NAME +#endif // ESP8266 + EOF # Parse and output contents of INPUT file. sed 's/ PROGMEM//' ${INPUT} | egrep "^(const )?char" | cut -f1 -d= | sed 's/ $/;/;s/^/extern /' | sort -u >> ${OUTPUT} - +egrep '^\s{,10}IRTEXT_CONST_STRING\(' ${INPUT} | cut -f2 -d\( | cut -f1 -d, | + sed 's/^/extern IRTEXT_CONST_PTR\(/;s/$/\);/' | sort -u >> ${OUTPUT} +egrep '^\s{,10}IRTEXT_CONST_BLOB_DECL\(' ${INPUT} | + cut -f2 -d\( | cut -f1 -d\) | + sed 's/^/extern IRTEXT_CONST_PTR\(/;s/$/\);/' | sort -u >> ${OUTPUT} # Footer cat >> ${OUTPUT} << EOF diff --git a/tools/mkkeywords b/tools/mkkeywords index 84f2a46fd..e050e4964 100755 --- a/tools/mkkeywords +++ b/tools/mkkeywords @@ -31,7 +31,8 @@ cat << EndOfTextEndOfTextEndOfText EndOfTextEndOfTextEndOfText CLASSES=$(egrep -h "^ *((enum|class) |} [a-zA-Z0-9_]+_t;$)" src/*.h | - sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u) + sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u | + grep -v "^__") for i in ${CLASSES}; do echo -e "${i}\tKEYWORD1" done | sort -du @@ -59,13 +60,15 @@ cat << EndOfTextEndOfTextEndOfText ####################################### EndOfTextEndOfTextEndOfText -LITERALS=$(grep "^#define [A-Z]" src/*.cpp src/*.h | +LITERALS=$(grep -h "^#define [A-Z]" src/*.cpp src/*.h | while read ignore define ignore; do echo ${define}; done | sort -u | grep -v [\(\)] | grep -v ^_ | grep -v _\$ | grep -v VIRTUAL) -CONSTS=$(grep "^const " src/*.cpp src/*.h | - sed -E 's/\[.*\] =.*//;s/ =.*//;s/^.* \*?k/k/') +CONSTS=$(grep -h "^const " src/*.cpp src/*.h | + sed -E 's/\[.*\] =.*//;s/ =.*//;s/^.* \*?k/k/'; + grep -h "^IRTEXT_CONST_" src/*.cpp src/*.h | + sed -E 's/IRTEXT_CONST_\S+\(//;s/,.*//;s/\).*//') ENUMS=$(cat src/*.h | while read a b; do if [[ ${a} == "};" ]]; then ENUM=0; @@ -76,7 +79,7 @@ ENUMS=$(cat src/*.h | while read a b; do if [[ ${a} == "enum" ]]; then ENUM=1; fi; - done) + done | grep -v "^//") for i in ${LITERALS} ${CONSTS} ${ENUMS}; do echo -e "${i}\tLITERAL1" done | sort -u