Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor ir_LG #1325

Merged
merged 2 commits into from
Nov 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 38 additions & 45 deletions src/ir_LG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ using irutils::addModeToString;
using irutils::addModelToString;
using irutils::addFanToString;
using irutils::addTempToString;
using irutils::setBit;
using irutils::setBits;


// Constants
Expand Down Expand Up @@ -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) {
Expand All @@ -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

Expand All @@ -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;
Expand All @@ -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();
}
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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;
}
Expand All @@ -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.
Expand All @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason for this comment being removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary

this->setMode(kLgAcAuto);
default:
_.Mode = kLgAcAuto;
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -477,25 +472,23 @@ 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;
}

/// 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);
}
49 changes: 26 additions & 23 deletions src/ir_LG.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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:
Expand All @@ -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);
};
Expand Down