diff --git a/src/ir_LG.cpp b/src/ir_LG.cpp index 828e45737..d78f25888 100644 --- a/src/ir_LG.cpp +++ b/src/ir_LG.cpp @@ -21,8 +21,6 @@ using irutils::addModeToString; using irutils::addModelToString; using irutils::addFanToString; using irutils::addTempToString; -using irutils::setBit; -using irutils::setBits; // Constants @@ -215,7 +213,7 @@ bool IRrecv::decodeLG(decode_results *results, uint16_t offset, /// @param[in] use_modulation Is frequency modulation to be used? IRLgAc::IRLgAc(const uint16_t pin, const bool inverted, const bool use_modulation) - : _irsend(pin, inverted, use_modulation) { this->stateReset(); } + : _irsend(pin, inverted, use_modulation) { stateReset(); } /// Reset the internals of the object to a known good state. void IRLgAc::stateReset(void) { @@ -230,12 +228,12 @@ void IRLgAc::begin(void) { _irsend.begin(); } /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. void IRLgAc::send(const uint16_t repeat) { - if (this->getPower()) - _irsend.send(this->_protocol, this->getRaw(), kLgBits, repeat); + if (getPower()) + _irsend.send(_protocol, getRaw(), kLgBits, repeat); else // Always send the special Off command if the power is set to off. // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1008#issuecomment-570763580 - _irsend.send(this->_protocol, kLgAcOffCommand, kLgBits, repeat); + _irsend.send(_protocol, kLgAcOffCommand, kLgBits, repeat); } #endif // SEND_LG @@ -255,7 +253,7 @@ void IRLgAc::setModel(const lg_ac_remote_model_t model) { /// Get the model of the A/C. /// @return The enum of the compatible model. -lg_ac_remote_model_t IRLgAc::getModel(void) { +lg_ac_remote_model_t IRLgAc::getModel(void) const { switch (_protocol) { case LG2: return lg_ac_remote_model_t::AKB75215403; @@ -270,13 +268,13 @@ lg_ac_remote_model_t IRLgAc::getModel(void) { /// @return The code for this protocol based on the current internal state. uint32_t IRLgAc::getRaw(void) { checksum(); - return remote_state; + return _.raw; } /// Set the internal state from a valid code for this protocol. /// @param[in] new_code A valid code for this protocol. void IRLgAc::setRaw(const uint32_t new_code) { - remote_state = new_code; + _.raw = new_code; _temp = 15; // Ensure there is a "sane" previous temp. _temp = getTemp(); } @@ -292,14 +290,14 @@ uint8_t IRLgAc::calcChecksum(const uint32_t state) { /// @param[in] state The value to verify the checksum of. /// @return true, if the state has a valid checksum. Otherwise, false. bool IRLgAc::validChecksum(const uint32_t state) { - return calcChecksum(state) == GETBITS32(state, kLgAcChecksumOffset, - kLgAcChecksumSize); + LGProtocol LGp; + LGp.raw = state; + return calcChecksum(state) == LGp.Sum; } /// Calculate and set the checksum values for the internal state. void IRLgAc::checksum(void) { - setBits(&remote_state, kLgAcChecksumOffset, kLgAcChecksumSize, - calcChecksum(remote_state)); + _.Sum = calcChecksum(_.raw); } /// Change the power setting to On. @@ -311,8 +309,7 @@ void IRLgAc::off(void) { setPower(false); } /// Change the power setting. /// @param[in] on true, the setting is on. false, the setting is off. void IRLgAc::setPower(const bool on) { - setBits(&remote_state, kLgAcPowerOffset, kLgAcPowerSize, - on ? kLgAcPowerOn : kLgAcPowerOff); + _.Power = (on ? kLgAcPowerOn : kLgAcPowerOff); if (on) setTemp(_temp); // Reset the temp if we are on. else @@ -321,16 +318,15 @@ void IRLgAc::setPower(const bool on) { /// Get the value of the current power setting. /// @return true, the setting is on. false, the setting is off. -bool IRLgAc::getPower(void) { - return GETBITS32(remote_state, kLgAcPowerOffset, kLgAcPowerSize) == - kLgAcPowerOn; +bool IRLgAc::getPower(void) const { + return _.Power == kLgAcPowerOn; } /// Set the temperature. /// @param[in] value The native temperature. /// @note Internal use only. -void IRLgAc::_setTemp(const uint8_t value) { - setBits(&remote_state, kLgAcTempOffset, kLgAcTempSize, value); +inline void IRLgAc::_setTemp(const uint8_t value) { + _.Temp = value; } /// Set the temperature. @@ -344,10 +340,9 @@ void IRLgAc::setTemp(const uint8_t degrees) { /// Get the current temperature setting. /// @return The current setting for temp. in degrees celsius. -uint8_t IRLgAc::getTemp(void) { +uint8_t IRLgAc::getTemp(void) const { if (getPower()) - return GETBITS32(remote_state, kLgAcTempOffset, kLgAcTempSize) + - kLgAcTempAdjust; + return _.Temp + kLgAcTempAdjust; else return _temp; } @@ -361,23 +356,23 @@ void IRLgAc::setFan(const uint8_t speed) { case kLgAcFanLow: case kLgAcFanMedium: case kLgAcFanHigh: - setBits(&remote_state, kLgAcFanOffset, kLgAcFanSize, speed); + _.Fan = speed; break; default: - setFan(kLgAcFanAuto); + _.Fan = kLgAcFanAuto; } } /// Get the current fan speed setting. /// @return The current fan speed. -uint8_t IRLgAc::getFan(void) { - return GETBITS32(remote_state, kLgAcFanOffset, kLgAcFanSize); +uint8_t IRLgAc::getFan(void) const { + return _.Fan; } /// Get the operating mode setting of the A/C. /// @return The current operating mode setting. -uint8_t IRLgAc::getMode(void) { - return GETBITS32(remote_state, kLgAcModeOffset, kLgAcModeSize); +uint8_t IRLgAc::getMode(void) const { + return _.Mode; } /// Set the operating mode of the A/C. @@ -389,10 +384,10 @@ void IRLgAc::setMode(const uint8_t mode) { case kLgAcHeat: case kLgAcCool: case kLgAcFan: - setBits(&remote_state, kLgAcModeOffset, kLgAcModeSize, mode); + _.Mode = mode; break; - default: // If we get an unexpected mode, default to AUTO. - this->setMode(kLgAcAuto); + default: + _.Mode = kLgAcAuto; } } @@ -451,15 +446,15 @@ stdAc::fanspeed_t IRLgAc::toCommonFanSpeed(const uint8_t speed) { /// Convert the current internal state into its stdAc::state_t equivalent. /// @return The stdAc equivalent of the native settings. -stdAc::state_t IRLgAc::toCommon(void) { +stdAc::state_t IRLgAc::toCommon(void) const { stdAc::state_t result; result.protocol = decode_type_t::LG; - result.model = this->getModel(); - result.power = this->getPower(); - result.mode = this->toCommonMode(this->getMode()); + result.model = getModel(); + result.power = getPower(); + result.mode = toCommonMode(_.Mode); result.celsius = true; - result.degrees = this->getTemp(); - result.fanspeed = this->toCommonFanSpeed(this->getFan()); + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(_.Fan); // Not supported. result.swingv = stdAc::swingv_t::kOff; result.swingh = stdAc::swingh_t::kOff; @@ -477,16 +472,16 @@ stdAc::state_t IRLgAc::toCommon(void) { /// Convert the current internal state into a human readable string. /// @return A human readable string. -String IRLgAc::toString(void) { +String IRLgAc::toString(void) const { String result = ""; result.reserve(80); // Reserve some heap for the string to reduce fragging. result += addModelToString(_protocol, getModel(), false); result += addBoolToString(getPower(), kPowerStr); if (getPower()) { // Only display the rest if is in power on state. - result += addModeToString(getMode(), kLgAcAuto, kLgAcCool, + result += addModeToString(_.Mode, kLgAcAuto, kLgAcCool, kLgAcHeat, kLgAcDry, kLgAcFan); result += addTempToString(getTemp()); - result += addFanToString(getFan(), kLgAcFanHigh, kLgAcFanLow, + result += addFanToString(_.Fan, kLgAcFanHigh, kLgAcFanLow, kLgAcFanAuto, kLgAcFanLowest, kLgAcFanMedium); } return result; @@ -494,8 +489,6 @@ String IRLgAc::toString(void) { /// Check if the internal state looks like a valid LG A/C message. /// @return true, the internal state is a valid LG A/C mesg. Otherwise, false. -bool IRLgAc::isValidLgAc(void) { - return validChecksum(remote_state) && - (GETBITS32(remote_state, kLgAcSignatureOffset, kLgAcSignatureSize) == - kLgAcSignature); +bool IRLgAc::isValidLgAc(void) const { + return validChecksum(_.raw) && (_.Sign == kLgAcSignature); } diff --git a/src/ir_LG.h b/src/ir_LG.h index 1748d143e..f02e9cb79 100644 --- a/src/ir_LG.h +++ b/src/ir_LG.h @@ -28,33 +28,36 @@ #include "IRsend_test.h" #endif -const uint8_t kLgAcChecksumOffset = 0; // Nr. of bits -const uint8_t kLgAcChecksumSize = kNibbleSize; // Nr. of bits -const uint8_t kLgAcFanOffset = 4; // Nr. of bits -const uint8_t kLgAcFanSize = 3; // Nr. of bits +/// Native representation of a LG A/C message. +union LGProtocol{ + uint32_t raw; ///< The state of the IR remote in IR code form. + struct { + uint32_t Sum :4; + uint32_t Fan :3; + uint32_t :1; + uint32_t Temp :4; + uint32_t Mode :3; + uint32_t :3; + uint32_t Power:2; + uint32_t Sign :8; + }; +}; + const uint8_t kLgAcFanLowest = 0; // 0b000 const uint8_t kLgAcFanLow = 1; // 0b001 const uint8_t kLgAcFanMedium = 2; // 0b010 const uint8_t kLgAcFanHigh = 4; // 0b100 const uint8_t kLgAcFanAuto = 5; // 0b101 -const uint8_t kLgAcTempOffset = 8; // Nr. of bits -const uint8_t kLgAcTempSize = 4; // Nr. of bits const uint8_t kLgAcTempAdjust = 15; const uint8_t kLgAcMinTemp = 16; // Celsius const uint8_t kLgAcMaxTemp = 30; // Celsius -const uint8_t kLgAcModeOffset = 12; // Nr. of bits -const uint8_t kLgAcModeSize = 3; // Nr. of bits const uint8_t kLgAcCool = 0; // 0b000 const uint8_t kLgAcDry = 1; // 0b001 const uint8_t kLgAcFan = 2; // 0b010 const uint8_t kLgAcAuto = 3; // 0b011 const uint8_t kLgAcHeat = 4; // 0b100 -const uint8_t kLgAcPowerOffset = 18; // Nr. of bits -const uint8_t kLgAcPowerSize = 2; // Nr. of bits const uint8_t kLgAcPowerOff = 3; // 0b11 const uint8_t kLgAcPowerOn = 0; // 0b00 -const uint8_t kLgAcSignatureOffset = 20; // Nr. of bits -const uint8_t kLgAcSignatureSize = 8; // Nr. of bits const uint8_t kLgAcSignature = 0x88; const uint32_t kLgAcOffCommand = 0x88C0051; @@ -68,7 +71,7 @@ class IRLgAc { void stateReset(void); static uint8_t calcChecksum(const uint32_t state); static bool validChecksum(const uint32_t state); - bool isValidLgAc(void); + bool isValidLgAc(void) const; #if SEND_LG void send(const uint16_t repeat = kLgDefaultRepeat); /// Run the calibration to calculate uSec timing offsets for this platform. @@ -81,23 +84,23 @@ class IRLgAc { void on(void); void off(void); void setPower(const bool on); - bool getPower(void); + bool getPower(void) const; void setTemp(const uint8_t degrees); - uint8_t getTemp(void); + uint8_t getTemp(void) const; void setFan(const uint8_t speed); - uint8_t getFan(void); + uint8_t getFan(void) const; void setMode(const uint8_t mode); - uint8_t getMode(void); + uint8_t getMode(void) const; uint32_t getRaw(void); void setRaw(const uint32_t new_code); - uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertMode(const stdAc::opmode_t mode); static stdAc::opmode_t toCommonMode(const uint8_t mode); static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); static uint8_t convertFan(const stdAc::fanspeed_t speed); - stdAc::state_t toCommon(void); - String toString(void); + stdAc::state_t toCommon(void) const; + String toString(void) const; void setModel(const lg_ac_remote_model_t model); - lg_ac_remote_model_t getModel(void); + lg_ac_remote_model_t getModel(void) const; #ifndef UNIT_TEST private: @@ -107,9 +110,9 @@ class IRLgAc { IRsendTest _irsend; ///< Instance of the testing IR send class /// @endcond #endif // UNIT_TEST - uint32_t remote_state; ///< The state of the IR remote in IR code form. + LGProtocol _; uint8_t _temp; - decode_type_t _protocol; + decode_type_t _protocol; ///< model void checksum(void); void _setTemp(const uint8_t value); };