From 61dd1588be250ac39d83a5cede05417e8a00c97f Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Mon, 4 Oct 2021 14:05:35 +1000 Subject: [PATCH 01/12] Strings finally in Flash! Finally convince the compiler to store the text strings into flash. Saves approx 1k of Global ram, and 1-1.5k of Flash space. Plus an overall reduction of ~1k on the resulting bin file size. e.g. * IRMQTTServer example code: - Before: RAM: [===== ] 53.2% (used 43560 bytes from 81920 bytes) Flash: [===== ] 53.1% (used 554500 bytes from 1044464 bytes) Bin file size = 558656 - After: RAM: [===== ] 52.0% (used 42572 bytes from 81920 bytes) Flash: [===== ] 53.0% (used 553448 bytes from 1044464 bytes) Bin file size = 557600 * IRrecvDumpV2 example code: - Before: RAM: [==== ] 37.0% (used 30348 bytes from 81920 bytes) Flash: [==== ] 35.4% (used 369644 bytes from 1044464 bytes) Bin file size = 373792 - After: RAM: [==== ] 35.9% (used 29372 bytes from 81920 bytes) Flash: [==== ] 35.2% (used 368036 bytes from 1044464 bytes) Bin file size = 372192 Fixes #1614 Fixes #1493 --- src/IRtext.cpp | 311 +++++++++++++++++++++++++------------------------ src/IRtext.h | 306 ++++++++++++++++++++++++------------------------ 2 files changed, 311 insertions(+), 306 deletions(-) diff --git a/src/IRtext.cpp b/src/IRtext.cpp index a8959d43e..07bc4b831 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -4,6 +4,7 @@ /// @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 #endif // UNIT_TEST @@ -15,179 +16,183 @@ #endif // 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; ///< +/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM doesn't work. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1493#issuecomment-933111219 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1614#issuecomment-928894559 +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; ///< ///< "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" +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" -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" +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" // 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" +const PROGMEM char kFanOnlyStr[] = D_STR_FANONLY; ///< "fan-only" +const PROGMEM char kFan_OnlyStr[] = D_STR_FAN_ONLY; ///< "fan_only" (legacy) +const PROGMEM char kFanOnlyWithSpaceStr[] = D_STR_FANSPACEONLY; ///< "Fan Only" +const PROGMEM char kFanOnlyNoSpaceStr[] = D_STR_FANONLYNOSPACE; ///< "FanOnly" -const PROGMEM char* kRecycleStr = D_STR_RECYCLE; ///< "Recycle" +const PROGMEM char 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" +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" -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" +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" // 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; ///< +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" +///< "Outside Quiet" +const PROGMEM char kOutsideQuietStr[] = D_STR_OUTSIDEQUIET; +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; ///< ///< "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; ///< +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; ///< ///< "Swing(V) Toggle" -const PROGMEM char* kTurboToggleStr = D_STR_TURBOTOGGLE; ///< "Turbo Toggle" +const PROGMEM char 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 PROGMEM char kSpaceLBraceStr[] = D_STR_SPACELBRACE; ///< " (" +const PROGMEM char kCommaSpaceStr[] = D_STR_COMMASPACE; ///< ", " +const PROGMEM char 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; ///< +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; ///< ///< "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" +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" -const PROGMEM char* kRepeatStr = D_STR_REPEAT; ///< "Repeat" -const PROGMEM char* kCodeStr = D_STR_CODE; ///< "Code" +const PROGMEM char kRepeatStr[] = D_STR_REPEAT; ///< "Repeat" +const PROGMEM char kCodeStr[] = D_STR_CODE; ///< "Code" const PROGMEM char* kBitsStr = D_STR_BITS; ///< "Bits" // Protocol Names diff --git a/src/IRtext.h b/src/IRtext.h index 20d1a958a..c04a836e1 100644 --- a/src/IRtext.h +++ b/src/IRtext.h @@ -13,160 +13,160 @@ // 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 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 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; +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[]; #endif // IRTEXT_H_ From 269cec60eb475c5a9c3be0e7aabebb945e9c2aa1 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Tue, 5 Oct 2021 09:59:08 +1000 Subject: [PATCH 02/12] Replace all ESP8266 `str*()`s with `_P` variants. Make sure any strlen() & strcasecmp()'s are replaced with strlen_P() & strcasecmp_P()'s on the ESP8266 platform. AFAIUI, the _P variants will handle non-flash located strs as well. Add a macro structure to allow overrides and allow minimal code changes. Note: Entire code base was checked for any `_P` possible replacements. * Example code was excluded (and it doesn't handle the flash stored strings anyway) i.e. Its safe. * `memcpy()`s exist but sources are not stored in flash at present. Convert some strings to Flash based via the `F()` macro. Ref: https://github.com/crankyoldgit/IRremoteESP8266/pull/1623#issuecomment-933633486 --- src/IRac.cpp | 244 ++++++++++++++++++++++++++---------------------- src/IRtext.cpp | 2 +- src/IRutils.cpp | 29 ++++-- 3 files changed, 155 insertions(+), 120 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index 9379914b1..35f28d330 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -50,6 +50,16 @@ #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 strcasecmp_P +#else // ESP8266 +#define STRCASECMP strcasecmp +#endif // ESP8266 +#endif // STRCASECMP + /// 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 +3069,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, F("COOLING"))) return stdAc::opmode_t::kCool; - else if (!strcasecmp(str, kHeatStr) || - !strcasecmp(str, "HEATING")) + else if (!STRCASECMP(str, kHeatStr) || + !STRCASECMP(str, F("HEATING"))) return stdAc::opmode_t::kHeat; - else if (!strcasecmp(str, kDryStr) || - !strcasecmp(str, "DRYING") || - !strcasecmp(str, "DEHUMIDIFY")) + else if (!STRCASECMP(str, kDryStr) || + !STRCASECMP(str, F("DRYING")) || + !STRCASECMP(str, F("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 +3105,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 +3136,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 +3177,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, F(D_STR_LEFT " " D_STR_MAX)) || // "Left Max" + !STRCASECMP(str, F(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, F(D_STR_RIGHT " " D_STR_MAX)) || // "Right Max" + !STRCASECMP(str, F(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 +3217,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, F("YAW1F"))) { return gree_ac_remote_model_t::YAW1F; - } else if (!strcasecmp(str, "YBOFB")) { + } else if (!STRCASECMP(str, F("YBOFB"))) { return gree_ac_remote_model_t::YBOFB; // HitachiAc1 models - } else if (!strcasecmp(str, "R-LT0541-HTA-A")) { + } else if (!STRCASECMP(str, F("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, F("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, F("ARRAH2E"))) { return fujitsu_ac_remote_model_t::ARRAH2E; - } else if (!strcasecmp(str, "ARDB1")) { + } else if (!STRCASECMP(str, F("ARDB1"))) { return fujitsu_ac_remote_model_t::ARDB1; - } else if (!strcasecmp(str, "ARREB1E")) { + } else if (!STRCASECMP(str, F("ARREB1E"))) { return fujitsu_ac_remote_model_t::ARREB1E; - } else if (!strcasecmp(str, "ARJW2")) { + } else if (!STRCASECMP(str, F("ARJW2"))) { return fujitsu_ac_remote_model_t::ARJW2; - } else if (!strcasecmp(str, "ARRY4")) { + } else if (!STRCASECMP(str, F("ARRY4"))) { return fujitsu_ac_remote_model_t::ARRY4; // LG A/C models - } else if (!strcasecmp(str, "GE6711AR2853M")) { + } else if (!STRCASECMP(str, F("GE6711AR2853M"))) { return lg_ac_remote_model_t::GE6711AR2853M; - } else if (!strcasecmp(str, "AKB75215403")) { + } else if (!STRCASECMP(str, F("AKB75215403"))) { return lg_ac_remote_model_t::AKB75215403; - } else if (!strcasecmp(str, "AKB74955603")) { + } else if (!STRCASECMP(str, F("AKB74955603"))) { return lg_ac_remote_model_t::AKB74955603; - } else if (!strcasecmp(str, "AKB73757604")) { + } else if (!STRCASECMP(str, F("AKB73757604"))) { return lg_ac_remote_model_t::AKB73757604; // Panasonic A/C families - } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) { + } else if (!STRCASECMP(str, F("LKE")) || + !STRCASECMP(str, F("PANASONICLKE"))) { return panasonic_ac_remote_model_t::kPanasonicLke; - } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) { + } else if (!STRCASECMP(str, F("NKE")) || + !STRCASECMP(str, F("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, F("DKE")) || + !STRCASECMP(str, F("PANASONICDKE")) || + !STRCASECMP(str, F("PKR")) || + !STRCASECMP(str, F("PANASONICPKR"))) { return panasonic_ac_remote_model_t::kPanasonicDke; - } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) { + } else if (!STRCASECMP(str, F("JKE")) || + !STRCASECMP(str, F("PANASONICJKE"))) { return panasonic_ac_remote_model_t::kPanasonicJke; - } else if (!strcasecmp(str, "CKP") || !strcasecmp(str, "PANASONICCKP")) { + } else if (!STRCASECMP(str, F("CKP")) || + !STRCASECMP(str, F("PANASONICCKP"))) { return panasonic_ac_remote_model_t::kPanasonicCkp; - } else if (!strcasecmp(str, "RKR") || !strcasecmp(str, "PANASONICRKR")) { + } else if (!STRCASECMP(str, F("RKR")) || + !STRCASECMP(str, F("PANASONICRKR"))) { return panasonic_ac_remote_model_t::kPanasonicRkr; // Sharp A/C Models - } else if (!strcasecmp(str, "A907")) { + } else if (!STRCASECMP(str, F("A907"))) { return sharp_ac_remote_model_t::A907; - } else if (!strcasecmp(str, "A705")) { + } else if (!STRCASECMP(str, F("A705"))) { return sharp_ac_remote_model_t::A705; - } else if (!strcasecmp(str, "A903")) { + } else if (!STRCASECMP(str, F("A903"))) { return sharp_ac_remote_model_t::A903; // TCL A/C Models - } else if (!strcasecmp(str, "TAC09CHSD")) { + } else if (!STRCASECMP(str, F("TAC09CHSD"))) { return tcl_ac_remote_model_t::TAC09CHSD; - } else if (!strcasecmp(str, "GZ055BE1")) { + } else if (!STRCASECMP(str, F("GZ055BE1"))) { return tcl_ac_remote_model_t::GZ055BE1; // Voltas A/C models - } else if (!strcasecmp(str, "122LZF")) { + } else if (!STRCASECMP(str, F("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, F("DG11J13A")) || + !STRCASECMP(str, F("DG11J104")) || + !STRCASECMP(str, F("DG11J1-04"))) { return whirlpool_ac_remote_model_t::DG11J13A; - } else if (!strcasecmp(str, "DG11J191")) { + } else if (!STRCASECMP(str, F("DG11J191"))) { return whirlpool_ac_remote_model_t::DG11J191; } else { int16_t number = atoi(str); @@ -3285,15 +3303,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, F("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, F("0")) || + !STRCASECMP(str, kNoStr) || + !STRCASECMP(str, kFalseStr)) return false; else return def; diff --git a/src/IRtext.cpp b/src/IRtext.cpp index 07bc4b831..bec4a09ce 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -1,4 +1,4 @@ -// 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: diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 905f0a04c..6dac8d538 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,23 @@ #include "IRsend.h" #include "IRtext.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 strcasecmp_P +#else // ESP8266 +#define STRCASECMP strcasecmp +#endif // ESP8266 +#endif // STRCASECMP +#ifndef STRLEN +#if defined(ESP8266) +#define STRLEN strlen_P +#else // ESP8266 +#define STRLEN strlen +#endif // ESP8266 +#endif // STRLEN + /// 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) @@ -94,11 +111,11 @@ void serialPrintUint64(uint64_t input, uint8_t base) { /// @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); + 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. @@ -121,12 +138,12 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { result = kUnknownStr; } else { - for (uint16_t i = 0; i <= protocol && strlen(ptr); i++) { + for (uint16_t i = 0; i <= protocol && STRLEN(ptr); i++) { if (i == protocol) { result = ptr; break; } - ptr += strlen(ptr) + 1; + ptr += STRLEN(ptr) + 1; } } if (isRepeat) { From 956defa72303851ce330902565e279ae63d752ef Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Tue, 5 Oct 2021 10:26:58 +1000 Subject: [PATCH 03/12] Oops. Change F() to PSTR(). --- src/IRac.cpp | 97 +++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index 35f28d330..e05953e5b 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -59,6 +59,9 @@ #define STRCASECMP strcasecmp #endif // ESP8266 #endif // STRCASECMP +#ifndef PSTR +#define PSTR +#endif /// Class constructor /// @param[in] pin Gpio pin to use when transmitting IR messages. @@ -3076,14 +3079,14 @@ stdAc::opmode_t IRac::strToOpmode(const char *str, !STRCASECMP(str, kStopStr)) return stdAc::opmode_t::kOff; else if (!STRCASECMP(str, kCoolStr) || - !STRCASECMP(str, F("COOLING"))) + !STRCASECMP(str, PSTR("COOLING"))) return stdAc::opmode_t::kCool; else if (!STRCASECMP(str, kHeatStr) || - !STRCASECMP(str, F("HEATING"))) + !STRCASECMP(str, PSTR("HEATING"))) return stdAc::opmode_t::kHeat; else if (!STRCASECMP(str, kDryStr) || - !STRCASECMP(str, F("DRYING")) || - !STRCASECMP(str, F("DEHUMIDIFY"))) + !STRCASECMP(str, PSTR("DRYING")) || + !STRCASECMP(str, PSTR("DEHUMIDIFY"))) return stdAc::opmode_t::kDry; else if (!STRCASECMP(str, kFanStr) || // The following Fans strings with "only" are required to help with @@ -3185,8 +3188,8 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, !STRCASECMP(str, kStopStr)) return stdAc::swingh_t::kOff; else if (!STRCASECMP(str, kLeftMaxStr) || // "LeftMax" - !STRCASECMP(str, F(D_STR_LEFT " " D_STR_MAX)) || // "Left Max" - !STRCASECMP(str, F(D_STR_MAX D_STR_LEFT)) || // "MaxLeft" + !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)) @@ -3200,8 +3203,8 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, else if (!STRCASECMP(str, kRightStr)) return stdAc::swingh_t::kRight; else if (!STRCASECMP(str, kRightMaxStr) || // "RightMax" - !STRCASECMP(str, F(D_STR_RIGHT " " D_STR_MAX)) || // "Right Max" - !STRCASECMP(str, F(D_STR_MAX D_STR_RIGHT)) || // "MaxRight" + !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)) @@ -3217,77 +3220,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, F("YAW1F"))) { + if (!STRCASECMP(str, PSTR("YAW1F"))) { return gree_ac_remote_model_t::YAW1F; - } else if (!STRCASECMP(str, F("YBOFB"))) { + } else if (!STRCASECMP(str, PSTR("YBOFB"))) { return gree_ac_remote_model_t::YBOFB; // HitachiAc1 models - } else if (!STRCASECMP(str, F("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, F("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, F("ARRAH2E"))) { + } else if (!STRCASECMP(str, PSTR("ARRAH2E"))) { return fujitsu_ac_remote_model_t::ARRAH2E; - } else if (!STRCASECMP(str, F("ARDB1"))) { + } else if (!STRCASECMP(str, PSTR("ARDB1"))) { return fujitsu_ac_remote_model_t::ARDB1; - } else if (!STRCASECMP(str, F("ARREB1E"))) { + } else if (!STRCASECMP(str, PSTR("ARREB1E"))) { return fujitsu_ac_remote_model_t::ARREB1E; - } else if (!STRCASECMP(str, F("ARJW2"))) { + } else if (!STRCASECMP(str, PSTR("ARJW2"))) { return fujitsu_ac_remote_model_t::ARJW2; - } else if (!STRCASECMP(str, F("ARRY4"))) { + } else if (!STRCASECMP(str, PSTR("ARRY4"))) { return fujitsu_ac_remote_model_t::ARRY4; // LG A/C models - } else if (!STRCASECMP(str, F("GE6711AR2853M"))) { + } else if (!STRCASECMP(str, PSTR("GE6711AR2853M"))) { return lg_ac_remote_model_t::GE6711AR2853M; - } else if (!STRCASECMP(str, F("AKB75215403"))) { + } else if (!STRCASECMP(str, PSTR("AKB75215403"))) { return lg_ac_remote_model_t::AKB75215403; - } else if (!STRCASECMP(str, F("AKB74955603"))) { + } else if (!STRCASECMP(str, PSTR("AKB74955603"))) { return lg_ac_remote_model_t::AKB74955603; - } else if (!STRCASECMP(str, F("AKB73757604"))) { + } else if (!STRCASECMP(str, PSTR("AKB73757604"))) { return lg_ac_remote_model_t::AKB73757604; // Panasonic A/C families - } else if (!STRCASECMP(str, F("LKE")) || - !STRCASECMP(str, F("PANASONICLKE"))) { + } else if (!STRCASECMP(str, PSTR("LKE")) || + !STRCASECMP(str, PSTR("PANASONICLKE"))) { return panasonic_ac_remote_model_t::kPanasonicLke; - } else if (!STRCASECMP(str, F("NKE")) || - !STRCASECMP(str, F("PANASONICNKE"))) { + } else if (!STRCASECMP(str, PSTR("NKE")) || + !STRCASECMP(str, PSTR("PANASONICNKE"))) { return panasonic_ac_remote_model_t::kPanasonicNke; - } else if (!STRCASECMP(str, F("DKE")) || - !STRCASECMP(str, F("PANASONICDKE")) || - !STRCASECMP(str, F("PKR")) || - !STRCASECMP(str, F("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, F("JKE")) || - !STRCASECMP(str, F("PANASONICJKE"))) { + } else if (!STRCASECMP(str, PSTR("JKE")) || + !STRCASECMP(str, PSTR("PANASONICJKE"))) { return panasonic_ac_remote_model_t::kPanasonicJke; - } else if (!STRCASECMP(str, F("CKP")) || - !STRCASECMP(str, F("PANASONICCKP"))) { + } else if (!STRCASECMP(str, PSTR("CKP")) || + !STRCASECMP(str, PSTR("PANASONICCKP"))) { return panasonic_ac_remote_model_t::kPanasonicCkp; - } else if (!STRCASECMP(str, F("RKR")) || - !STRCASECMP(str, F("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, F("A907"))) { + } else if (!STRCASECMP(str, PSTR("A907"))) { return sharp_ac_remote_model_t::A907; - } else if (!STRCASECMP(str, F("A705"))) { + } else if (!STRCASECMP(str, PSTR("A705"))) { return sharp_ac_remote_model_t::A705; - } else if (!STRCASECMP(str, F("A903"))) { + } else if (!STRCASECMP(str, PSTR("A903"))) { return sharp_ac_remote_model_t::A903; // TCL A/C Models - } else if (!STRCASECMP(str, F("TAC09CHSD"))) { + } else if (!STRCASECMP(str, PSTR("TAC09CHSD"))) { return tcl_ac_remote_model_t::TAC09CHSD; - } else if (!STRCASECMP(str, F("GZ055BE1"))) { + } else if (!STRCASECMP(str, PSTR("GZ055BE1"))) { return tcl_ac_remote_model_t::GZ055BE1; // Voltas A/C models - } else if (!STRCASECMP(str, F("122LZF"))) { + } else if (!STRCASECMP(str, PSTR("122LZF"))) { return voltas_ac_remote_model_t::kVoltas122LZF; // Whirlpool A/C models - } else if (!STRCASECMP(str, F("DG11J13A")) || - !STRCASECMP(str, F("DG11J104")) || - !STRCASECMP(str, F("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, F("DG11J191"))) { + } else if (!STRCASECMP(str, PSTR("DG11J191"))) { return whirlpool_ac_remote_model_t::DG11J191; } else { int16_t number = atoi(str); @@ -3304,12 +3307,12 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { /// @return The equivalent boolean value. bool IRac::strToBool(const char *str, const bool def) { if (!STRCASECMP(str, kOnStr) || - !STRCASECMP(str, F("1")) || + !STRCASECMP(str, PSTR("1")) || !STRCASECMP(str, kYesStr) || !STRCASECMP(str, kTrueStr)) return true; else if (!STRCASECMP(str, kOffStr) || - !STRCASECMP(str, F("0")) || + !STRCASECMP(str, PSTR("0")) || !STRCASECMP(str, kNoStr) || !STRCASECMP(str, kFalseStr)) return false; From dcdabd7d81bad44c1504dffa3ad4ab7ae4f1e093 Mon Sep 17 00:00:00 2001 From: David Conran Date: Thu, 7 Oct 2021 15:14:26 +1000 Subject: [PATCH 04/12] wip (#1629) Co-authored-by: Maxim Prokhorov --- src/IRac.cpp | 4 +- src/IRtext.cpp | 337 ++++++++++++++++++++++------------------- src/IRtext.h | 320 +++++++++++++++++++------------------- src/IRutils.cpp | 8 +- src/ir_Electra.cpp | 2 +- src/ir_Goodweather.cpp | 7 +- src/ir_Sharp.cpp | 8 +- 7 files changed, 358 insertions(+), 328 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index e05953e5b..162d4dde7 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -54,9 +54,9 @@ // functions to handle the strings stored in the flash address space. #ifndef STRCASECMP #if defined(ESP8266) -#define STRCASECMP strcasecmp_P +#define STRCASECMP(LHS, RHS) strcasecmp_P(LHS, reinterpret_cast(RHS)) #else // ESP8266 -#define STRCASECMP strcasecmp +#define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS) #endif // ESP8266 #endif // STRCASECMP #ifndef PSTR diff --git a/src/IRtext.cpp b/src/IRtext.cpp index bec4a09ce..8120774df 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -15,189 +15,207 @@ #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 + // Common -/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM doesn't work. +/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM only applies to the pointer and not the actual data. /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1493#issuecomment-933111219 /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1614#issuecomment-928894559 -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; ///< + +#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) { FPSTR(IRTEXT_CONST_BLOB_NAME(NAME)) } + +#define IRTEXT_CONST_STRING(NAME, VALUE)\ + static IRTEXT_CONST_BLOB_DECL(NAME) { VALUE };\ + IRTEXT_CONST_PTR(NAME) PROGMEM { FPSTR(&(NAME ## Blob)[0]) } + +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) -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" +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" -const PROGMEM char kOutsideQuietStr[] = D_STR_OUTSIDEQUIET; -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(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" @@ -307,4 +325,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 c04a836e1..a21c743f0 100644 --- a/src/IRtext.h +++ b/src/IRtext.h @@ -12,161 +12,169 @@ // 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[]; +extern const char kTimeSep; + +#ifdef ESP8266 +class __FlashStringHelper; +#define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME +#else +#define IRTEXT_CONST_PTR(NAME) const char* const NAME +#endif + +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(kAllProtocolNamesStr); +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); #endif // IRTEXT_H_ diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 6dac8d538..1d8e4b540 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -21,14 +21,14 @@ // functions to handle the strings stored in the flash address space. #ifndef STRCASECMP #if defined(ESP8266) -#define STRCASECMP strcasecmp_P +#define STRCASECMP(LHS, RHS) strcasecmp_P(LHS, reinterpret_cast(RHS)) #else // ESP8266 #define STRCASECMP strcasecmp #endif // ESP8266 #endif // STRCASECMP #ifndef STRLEN #if defined(ESP8266) -#define STRLEN strlen_P +#define STRLEN(X) strlen_P(reinterpret_cast(X)) #else // ESP8266 #define STRLEN strlen #endif // ESP8266 @@ -110,7 +110,7 @@ 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; + auto *ptr = reinterpret_cast(kAllProtocolNamesStr); uint16_t length = STRLEN(ptr); for (uint16_t i = 0; length; i++) { if (!STRCASECMP(str, ptr)) return (decode_type_t)i; @@ -134,7 +134,7 @@ 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; + auto *ptr = reinterpret_cast(kAllProtocolNamesStr); if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { result = kUnknownStr; } else { diff --git a/src/ir_Electra.cpp b/src/ir_Electra.cpp index fd70e4bd6..13ea10dd4 100644 --- a/src/ir_Electra.cpp +++ b/src/ir_Electra.cpp @@ -351,7 +351,7 @@ 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..a61fa2aa3 100644 --- a/src/ir_Goodweather.cpp +++ b/src/ir_Goodweather.cpp @@ -346,9 +346,10 @@ 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..e68bf74d4 100644 --- a/src/ir_Sharp.cpp +++ b/src/ir_Sharp.cpp @@ -870,8 +870,8 @@ 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 +919,11 @@ 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); From f47dd07b4ae4c8eab6267d3a28617dd30d6e0ac5 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Thu, 7 Oct 2021 15:25:20 +1000 Subject: [PATCH 05/12] Fix introduced linter errors/issues. --- src/IRac.cpp | 3 ++- src/IRtext.cpp | 5 +++-- src/IRutils.cpp | 3 ++- src/ir_Electra.cpp | 3 ++- src/ir_Goodweather.cpp | 9 ++++++--- src/ir_Sharp.cpp | 9 ++++++--- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index 162d4dde7..ea102fc87 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -54,7 +54,8 @@ // 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(RHS)) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast(RHS)) #else // ESP8266 #define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS) #endif // ESP8266 diff --git a/src/IRtext.cpp b/src/IRtext.cpp index 8120774df..a28ae73cd 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -16,11 +16,12 @@ #endif #ifndef FPSTR -#define FPSTR(X) X // Also pretend we have flash-string helper class cast. +#define FPSTR(X) X // Also pretend we have flash-string helper class cast. #endif // Common -/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM only applies to the pointer and not the actual data. +/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM only applies +/// to the pointer and not the actual data. /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1493#issuecomment-933111219 /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1614#issuecomment-928894559 diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 1d8e4b540..691b57b8a 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -21,7 +21,8 @@ // 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(RHS)) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast(RHS)) #else // ESP8266 #define STRCASECMP strcasecmp #endif // ESP8266 diff --git a/src/ir_Electra.cpp b/src/ir_Electra.cpp index 13ea10dd4..e48a19487 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() ? String(kToggleStr) : String('-'), 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 a61fa2aa3..75883c0f4 100644 --- a/src/ir_Goodweather.cpp +++ b/src/ir_Goodweather.cpp @@ -347,9 +347,12 @@ String IRGoodweatherAc::toString(void) const { kGoodweatherFanAuto, kGoodweatherFanAuto, kGoodweatherFanMed); - result += addLabeledString(_.Turbo ? String(kToggleStr) : String('-'), kTurboStr); - result += addLabeledString(_.Light ? String(kToggleStr) : String('-'), kLightStr); - result += addLabeledString(_.Sleep ? String(kToggleStr) : String('-'), 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 e68bf74d4..1a79d381f 100644 --- a/src/ir_Sharp.cpp +++ b/src/ir_Sharp.cpp @@ -871,7 +871,8 @@ String IRSharpAc::toString(void) const { result += addModelToString(decode_type_t::SHARP_AC, getModel(), false); result += addLabeledString(isPowerSpecial() ? String('-') - : String(getPower() ? kOnStr : kOffStr), + : 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() ? String(kToggleStr) : String('-'), + result += addLabeledString(getLightToggle() ? String(kToggleStr) + : String('-'), kLightStr); break; default: - result += addLabeledString(getEconoToggle() ? String(kToggleStr) : String('-'), + result += addLabeledString(getEconoToggle() ? String(kToggleStr) + : String('-'), kEconoStr); } result += addBoolToString(_.Clean, kCleanStr); From 81aaddace1528a2e912c5998c1b3cffd45a27667 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Thu, 7 Oct 2021 17:51:43 +1000 Subject: [PATCH 06/12] Fix code compilation errors and unit test fails. --- src/IRutils.cpp | 53 ++++++++++++++++++++++++++---------------- src/ir_Electra.cpp | 2 +- src/ir_Goodweather.cpp | 6 ++--- src/ir_Sharp.cpp | 6 ++--- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 691b57b8a..d6b367745 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -27,13 +27,9 @@ #define STRCASECMP strcasecmp #endif // ESP8266 #endif // STRCASECMP -#ifndef STRLEN -#if defined(ESP8266) -#define STRLEN(X) strlen_P(reinterpret_cast(X)) -#else // ESP8266 -#define STRLEN strlen -#endif // ESP8266 -#endif // STRLEN +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*reinterpret_cast(addr)) +#endif // pgm_read_byte /// Reverse the order of the requested least significant nr. of bits. /// @param[in] input Bit pattern/integer to reverse. @@ -111,14 +107,23 @@ 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) { - auto *ptr = reinterpret_cast(kAllProtocolNamesStr); - uint16_t length = STRLEN(ptr); - for (uint16_t i = 0; length; i++) { - if (!STRCASECMP(str, ptr)) return (decode_type_t)i; - ptr += length + 1; - length = STRLEN(ptr); + const char *ptr = kAllProtocolNamesStr; + const uint8_t kProtocolNameLength = 30; + uint32_t count = 0; + char protoname[kProtocolNameLength + 1] = ""; + for (int8_t i = 0; i < kProtocolNameLength; i++) { + const uint8_t c = pgm_read_byte(ptr++); + protoname[i] = c; + if (!c) { // End of the C-str. + if (!strncasecmp(str, protoname, kProtocolNameLength)) + return (decode_type_t)count; // Found it! + // Break out of this loop if we've reached the end. ie. protoname is empty + if (!i) break; + // Start reading in the next protocol name. + i = -1; + count++; + } } - // 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()); @@ -135,16 +140,24 @@ 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)" - auto *ptr = reinterpret_cast(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; + const char *ptr = kAllProtocolNamesStr; + bool found = false; + for (uint16_t i = 0; + i <= protocol && pgm_read_byte(ptr) && !found; + i++) { + // Read till the end of the C-str. + for (char c = pgm_read_byte(ptr); c ; c = pgm_read_byte(++ptr)) { + if (i == protocol) { + // We've found the string for out protocol, so add it to the result + // character by character. + found = true; + result += c; + } } - ptr += STRLEN(ptr) + 1; + ptr++; // Skip over the end of the C-str NUL terminator. } } if (isRepeat) { diff --git a/src/ir_Electra.cpp b/src/ir_Electra.cpp index e48a19487..864ab82d6 100644 --- a/src/ir_Electra.cpp +++ b/src/ir_Electra.cpp @@ -352,7 +352,7 @@ String IRElectraAc::toString(void) const { result += addBoolToString(getSwingV(), kSwingVStr); result += addBoolToString(getSwingH(), kSwingHStr); result += addLabeledString(getLightToggle() ? String(kToggleStr) - : String('-'), kLightStr); + : 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 75883c0f4..2ddcb2aa2 100644 --- a/src/ir_Goodweather.cpp +++ b/src/ir_Goodweather.cpp @@ -348,11 +348,11 @@ String IRGoodweatherAc::toString(void) const { kGoodweatherFanMed); result += addLabeledString(_.Turbo ? String(kToggleStr) - : String('-'), kTurboStr); + : String("-"), kTurboStr); result += addLabeledString(_.Light ? String(kToggleStr) - : String('-'), kLightStr); + : String("-"), kLightStr); result += addLabeledString(_.Sleep ? String(kToggleStr) - : String('-'), kSleepStr); + : String("-"), kSleepStr); result += addIntToString(_.Swing, kSwingStr); result += kSpaceLBraceStr; switch (_.Swing) { diff --git a/src/ir_Sharp.cpp b/src/ir_Sharp.cpp index 1a79d381f..29be0dee3 100644 --- a/src/ir_Sharp.cpp +++ b/src/ir_Sharp.cpp @@ -870,7 +870,7 @@ 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() ? String('-') + result += addLabeledString(isPowerSpecial() ? String("-") : String(getPower() ? kOnStr : kOffStr), kPowerStr); @@ -921,12 +921,12 @@ String IRSharpAc::toString(void) const { case sharp_ac_remote_model_t::A705: case sharp_ac_remote_model_t::A903: result += addLabeledString(getLightToggle() ? String(kToggleStr) - : String('-'), + : String("-"), kLightStr); break; default: result += addLabeledString(getEconoToggle() ? String(kToggleStr) - : String('-'), + : String("-"), kEconoStr); } result += addBoolToString(_.Clean, kCleanStr); From 72103fbc7bb9bde4ae5370bd32a0f32e1d2ef8c0 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Thu, 7 Oct 2021 17:57:06 +1000 Subject: [PATCH 07/12] Fix doxygen warnings. --- src/IRtext.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/IRtext.cpp b/src/IRtext.cpp index a28ae73cd..4cef6088e 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -19,12 +19,6 @@ #define FPSTR(X) X // Also pretend we have flash-string helper class cast. #endif -// Common -/// @note Use `char array[]`, not `char *array`, otherwise PROGMEM only applies -/// to the pointer and not the actual data. -/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1493#issuecomment-933111219 -/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1614#issuecomment-928894559 - #define IRTEXT_CONST_BLOB_NAME(NAME)\ NAME ## Blob @@ -38,6 +32,7 @@ static IRTEXT_CONST_BLOB_DECL(NAME) { VALUE };\ IRTEXT_CONST_PTR(NAME) PROGMEM { FPSTR(&(NAME ## Blob)[0]) } +// Common IRTEXT_CONST_STRING(kUnknownStr, D_STR_UNKNOWN); ///< "Unknown" IRTEXT_CONST_STRING(kProtocolStr, D_STR_PROTOCOL); ///< "Protocol" IRTEXT_CONST_STRING(kPowerStr, D_STR_POWER); ///< "Power" From 9bc12a8b12504456c9bfca850c5d0c2c245367f6 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Thu, 7 Oct 2021 18:34:15 +1000 Subject: [PATCH 08/12] Update IRtext.h generator. --- src/IRtext.h | 9 ++++----- tools/generate_irtext_h.sh | 13 ++++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/IRtext.h b/src/IRtext.h index a21c743f0..c1c9332cf 100644 --- a/src/IRtext.h +++ b/src/IRtext.h @@ -12,21 +12,19 @@ // Constant text to be shared across all object files. // This means there is only one copy of the character/string/text etc. -extern const char kTimeSep; - #ifdef ESP8266 class __FlashStringHelper; #define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME -#else +#else // ESP8266 #define IRTEXT_CONST_PTR(NAME) const char* const NAME -#endif +#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(kAllProtocolNamesStr); extern IRTEXT_CONST_PTR(kAutomaticStr); extern IRTEXT_CONST_PTR(kAutoStr); extern IRTEXT_CONST_PTR(kBeepStr); @@ -176,5 +174,6 @@ 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/tools/generate_irtext_h.sh b/tools/generate_irtext_h.sh index df2baee06..0017a45ad 100755 --- a/tools/generate_irtext_h.sh +++ b/tools/generate_irtext_h.sh @@ -24,12 +24,23 @@ 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(NAME) const __FlashStringHelper* const NAME +#else // ESP8266 +#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 From 079285ad79813a3531f6d16575fda5c5aed26c54 Mon Sep 17 00:00:00 2001 From: David Conran Date: Fri, 8 Oct 2021 11:11:57 +1000 Subject: [PATCH 09/12] Strings in flash flashstringtype (#1631) * fix esp32 build flashstringhelper casts * try to revert the original type<->string, use correct types Authored-by: Maxim Prokhorov --- src/IRtext.cpp | 4 +-- src/IRtext.h | 3 ++ src/IRutils.cpp | 62 ++++++++++++++++++-------------------- tools/generate_irtext_h.sh | 3 ++ 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/IRtext.cpp b/src/IRtext.cpp index 4cef6088e..1f8261ffe 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -26,11 +26,11 @@ const char IRTEXT_CONST_BLOB_NAME(NAME) [] PROGMEM #define IRTEXT_CONST_BLOB_PTR(NAME)\ - IRTEXT_CONST_PTR(NAME) { FPSTR(IRTEXT_CONST_BLOB_NAME(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 { FPSTR(&(NAME ## Blob)[0]) } + IRTEXT_CONST_PTR(NAME) PROGMEM { IRTEXT_CONST_PTR_CAST(&(IRTEXT_CONST_BLOB_NAME(NAME))[0]) } // Common IRTEXT_CONST_STRING(kUnknownStr, D_STR_UNKNOWN); ///< "Unknown" diff --git a/src/IRtext.h b/src/IRtext.h index c1c9332cf..589cd38ef 100644 --- a/src/IRtext.h +++ b/src/IRtext.h @@ -14,8 +14,11 @@ #ifdef ESP8266 class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\ + reinterpret_cast(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 diff --git a/src/IRutils.cpp b/src/IRutils.cpp index d6b367745..c94c9eab2 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -17,16 +17,26 @@ #include "IRsend.h" #include "IRtext.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. +// 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(RHS)) + strcasecmp_P(LHS, reinterpret_cast(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 #ifndef pgm_read_byte #define pgm_read_byte(addr) (*reinterpret_cast(addr)) #endif // pgm_read_byte @@ -107,30 +117,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; - const uint8_t kProtocolNameLength = 30; - uint32_t count = 0; - char protoname[kProtocolNameLength + 1] = ""; - for (int8_t i = 0; i < kProtocolNameLength; i++) { - const uint8_t c = pgm_read_byte(ptr++); - protoname[i] = c; - if (!c) { // End of the C-str. - if (!strncasecmp(str, protoname, kProtocolNameLength)) - return (decode_type_t)count; // Found it! - // Break out of this loop if we've reached the end. ie. protoname is empty - if (!i) break; - // Start reading in the next protocol name. - i = -1; - count++; - } + auto *ptr = reinterpret_cast(kAllProtocolNamesStr); + uint16_t length = STRLEN(ptr); + for (uint16_t i = 0; length; i++) { + if (!STRCASECMP(str, ptr)) return (decode_type_t)i; + ptr += length + 1; + 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. @@ -143,21 +143,17 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { result = kUnknownStr; } else { - const char *ptr = kAllProtocolNamesStr; - bool found = false; - for (uint16_t i = 0; - i <= protocol && pgm_read_byte(ptr) && !found; - i++) { - // Read till the end of the C-str. - for (char c = pgm_read_byte(ptr); c ; c = pgm_read_byte(++ptr)) { + auto *ptr = reinterpret_cast(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) { - // We've found the string for out protocol, so add it to the result - // character by character. - found = true; - result += c; + result = FPSTR(ptr); + break; } + ptr += STRLEN(ptr) + 1; } - ptr++; // Skip over the end of the C-str NUL terminator. } } if (isRepeat) { diff --git a/tools/generate_irtext_h.sh b/tools/generate_irtext_h.sh index 0017a45ad..b0d9855c4 100755 --- a/tools/generate_irtext_h.sh +++ b/tools/generate_irtext_h.sh @@ -26,8 +26,11 @@ cat >${OUTPUT} << EOF #ifdef ESP8266 class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\\ + reinterpret_cast(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 From 04b92c048a74b9222ba463db52fc3df969430f3b Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Fri, 8 Oct 2021 11:15:43 +1000 Subject: [PATCH 10/12] Fix linter issues. Fix: ``` src/IRtext.cpp:29: Lines should be <= 80 characters long [whitespace/line_length] [2] src/IRtext.cpp:33: Lines should be <= 80 characters long [whitespace/line_length] [2] ``` --- src/IRtext.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/IRtext.cpp b/src/IRtext.cpp index 1f8261ffe..8cca392b3 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -26,11 +26,13 @@ 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)) } + 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]) } + IRTEXT_CONST_PTR(NAME) PROGMEM {\ + IRTEXT_CONST_PTR_CAST(&(IRTEXT_CONST_BLOB_NAME(NAME))[0]) } // Common IRTEXT_CONST_STRING(kUnknownStr, D_STR_UNKNOWN); ///< "Unknown" From da72355daa401fc1f7aaf70986970b76630ed890 Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Fri, 8 Oct 2021 22:56:19 +1000 Subject: [PATCH 11/12] Minor code cleanup. --- src/IRac.cpp | 8 ++++---- src/IRutils.cpp | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/IRac.cpp b/src/IRac.cpp index ea102fc87..9623c98d7 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -3188,10 +3188,10 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, else if (!STRCASECMP(str, kOffStr) || !STRCASECMP(str, kStopStr)) return stdAc::swingh_t::kOff; - else if (!STRCASECMP(str, kLeftMaxStr) || // "LeftMax" + 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" + !STRCASECMP(str, kMaxLeftStr)) // "Max Left" return stdAc::swingh_t::kLeftMax; else if (!STRCASECMP(str, kLeftStr)) return stdAc::swingh_t::kLeft; @@ -3203,10 +3203,10 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, return stdAc::swingh_t::kMiddle; else if (!STRCASECMP(str, kRightStr)) return stdAc::swingh_t::kRight; - else if (!STRCASECMP(str, kRightMaxStr) || // "RightMax" + 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" + !STRCASECMP(str, kMaxRightStr)) // "Max Right" return stdAc::swingh_t::kRightMax; else if (!STRCASECMP(str, kWideStr)) return stdAc::swingh_t::kWide; diff --git a/src/IRutils.cpp b/src/IRutils.cpp index c94c9eab2..4154f7290 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -37,9 +37,6 @@ #ifndef FPSTR #define FPSTR(X) X #endif // FPSTR -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*reinterpret_cast(addr)) -#endif // pgm_read_byte /// Reverse the order of the requested least significant nr. of bits. /// @param[in] input Bit pattern/integer to reverse. From fc3d3d8ce5ea6486dab01e2b601a0a77c1ad54fe Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Sat, 9 Oct 2021 07:29:31 +1000 Subject: [PATCH 12/12] Update tools/mkkeywords * Handle new constant structure for strings. * Fix some other niggling issues. --- keywords.txt | 47 +++++++++++++++++++++++++++++++++++++++++++++-- tools/mkkeywords | 13 ++++++++----- 2 files changed, 53 insertions(+), 7 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/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