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

HITACHI_AC264: Add minimal detailed support. #1735

Merged
merged 4 commits into from
Jan 20, 2022
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
55 changes: 55 additions & 0 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_HITACHI_AC1
case decode_type_t::HITACHI_AC1:
#endif
#if SEND_HITACHI_AC264
case decode_type_t::HITACHI_AC264:
#endif
#if SEND_HITACHI_AC344
case decode_type_t::HITACHI_AC344:
#endif
Expand Down Expand Up @@ -1313,6 +1316,35 @@ void IRac::hitachi1(IRHitachiAc1 *ac, const hitachi_ac1_remote_model_t model,
}
#endif // SEND_HITACHI_AC1

#if SEND_HITACHI_AC264
/// Send a Hitachi 264-bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRHitachiAc264 object to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] fan The speed setting for the fan.
void IRac::hitachi264(IRHitachiAc264 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan) {
ac->begin();
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setPower(on);
// No Swing(V) setting available.
// No Swing(H) setting available.
// No Quiet setting available.
// No Turbo setting available.
// No Light setting available.
// No Filter setting available.
// No Clean setting available.
// No Beep setting available.
// No Sleep setting available.
// No Clock setting available.
ac->send();
}
#endif // SEND_HITACHI_AC264

#if SEND_HITACHI_AC344
/// Send a Hitachi 344-bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRHitachiAc344 object to use.
Expand Down Expand Up @@ -2903,6 +2935,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_HITACHI_AC1
#if SEND_HITACHI_AC264
case HITACHI_AC264:
{
IRHitachiAc264 ac(_pin, _inverted, _modulation);
hitachi264(&ac, send.power, send.mode, degC, send.fanspeed);
break;
}
#endif // SEND_HITACHI_AC264
#if SEND_HITACHI_AC344
case HITACHI_AC344:
{
Expand Down Expand Up @@ -3756,6 +3796,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_HITACHI_AC1
#if DECODE_HITACHI_AC264
case decode_type_t::HITACHI_AC264: {
IRHitachiAc264 ac(kGpioUnused);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_HITACHI_AC264
#if DECODE_HITACHI_AC344
case decode_type_t::HITACHI_AC344: {
IRHitachiAc344 ac(kGpioUnused);
Expand Down Expand Up @@ -4213,6 +4260,14 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_HITACHI_AC1
#if DECODE_HITACHI_AC264
case decode_type_t::HITACHI_AC264: {
IRHitachiAc264 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_HITACHI_AC264
#if DECODE_HITACHI_AC344
case decode_type_t::HITACHI_AC344: {
IRHitachiAc344 ac(kGpioUnused);
Expand Down
5 changes: 5 additions & 0 deletions src/IRac.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ void electra(IRElectraAc *ac,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool swing_toggle, const int16_t sleep = -1);
#endif // SEND_HITACHI_AC1
#if SEND_HITACHI_AC264
void hitachi264(IRHitachiAc264 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan);
#endif // SEND_HITACHI_AC264
#if SEND_HITACHI_AC344
void hitachi344(IRHitachiAc344 *ac,
const bool on, const stdAc::opmode_t mode,
Expand Down
100 changes: 94 additions & 6 deletions src/ir_Hitachi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,7 @@ void IRHitachiAc424::stateReset(void) {
_.raw[3] = 0x40;
_.raw[5] = 0xFF;
_.raw[7] = 0xCC;
_.raw[27] = 0xE1;
_.raw[33] = 0x80;
_.raw[35] = 0x03;
_.raw[37] = 0x01;
Expand Down Expand Up @@ -1072,15 +1073,13 @@ void IRHitachiAc424::send(const uint16_t repeat) {

/// Get the value of the current power setting.
/// @return true, the setting is on. false, the setting is off.
bool IRHitachiAc424::getPower(void) const {
return _.Power == kHitachiAc424PowerOn;
}
bool IRHitachiAc424::getPower(void) const { return _.Power; }

/// Change the power setting.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRHitachiAc424::setPower(const bool on) {
_.Power = on;
setButton(kHitachiAc424ButtonPowerMode);
_.Power = (on ? kHitachiAc424PowerOn : kHitachiAc424PowerOff);
}

/// Change the power setting to On.
Expand Down Expand Up @@ -1220,7 +1219,7 @@ uint8_t IRHitachiAc424::convertMode(const stdAc::opmode_t mode) {
/// Convert a stdAc::fanspeed_t enum into it's native speed.
/// @param[in] speed The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRHitachiAc424::convertFan(const stdAc::fanspeed_t speed) {
uint8_t IRHitachiAc424::convertFan(const stdAc::fanspeed_t speed) const {
switch (speed) {
case stdAc::fanspeed_t::kMin: return kHitachiAc424FanMin;
case stdAc::fanspeed_t::kLow: return kHitachiAc424FanLow;
Expand All @@ -1247,7 +1246,7 @@ stdAc::opmode_t IRHitachiAc424::toCommonMode(const uint8_t mode) {
/// Convert a native fan speed into its stdAc equivalent.
/// @param[in] speed The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::fanspeed_t IRHitachiAc424::toCommonFanSpeed(const uint8_t speed) {
stdAc::fanspeed_t IRHitachiAc424::toCommonFanSpeed(const uint8_t speed) const {
switch (speed) {
case kHitachiAc424FanMax: return stdAc::fanspeed_t::kMax;
case kHitachiAc424FanHigh: return stdAc::fanspeed_t::kHigh;
Expand Down Expand Up @@ -1613,6 +1612,95 @@ void IRsend::sendHitachiAc264(const unsigned char data[], const uint16_t nbytes,
}
#endif // SEND_HITACHI_AC264

// Class constructor for handling detailed Hitachi_AC344 43 byte A/C messages.
/// @param[in] pin GPIO to be used when sending.
/// @param[in] inverted Is the output signal to be inverted?
/// @param[in] use_modulation Is frequency modulation to be used?
IRHitachiAc264::IRHitachiAc264(const uint16_t pin, const bool inverted,
const bool use_modulation)
: IRHitachiAc424(pin, inverted, use_modulation) { stateReset(); }

/// Reset the internal state to auto fan, cooling, 23° Celsius
void IRHitachiAc264::stateReset(void) {
IRHitachiAc424::stateReset();
_.raw[9] = 0x92;
_.raw[27] = 0xC1;
}

#if SEND_HITACHI_AC264
/// Create and send the IR message to the A/C.
/// @param[in] repeat Nr. of times to repeat the message.
void IRHitachiAc264::send(const uint16_t repeat) {
_irsend.sendHitachiAc264(getRaw(), kHitachiAc264StateLength, repeat);
}
#endif // SEND_HITACHI_AC264

/// Set the internal state from a valid code for this protocol.
/// @param[in] new_code A valid code for this protocol.
/// @param[in] length Size (in bytes) of the code for this protocol.
void IRHitachiAc264::setRaw(const uint8_t new_code[], const uint16_t length) {
memcpy(_.raw, new_code, std::min(length, kHitachiAc264StateLength));
}

/// Set the speed of the fan.
/// @param[in] speed The desired setting.
void IRHitachiAc264::setFan(const uint8_t speed) {
switch (speed) {
case kHitachiAc264FanMin:
case kHitachiAc264FanMedium:
case kHitachiAc264FanHigh:
case kHitachiAc264FanAuto:
_.Fan = speed;
break;
default:
setFan(kHitachiAc264FanAuto);
}
}

/// Convert a stdAc::fanspeed_t enum into it's native speed.
/// @param[in] speed The enum to be converted.
/// @return The native equivalent of the enum.
uint8_t IRHitachiAc264::convertFan(const stdAc::fanspeed_t speed) const {
switch (speed) {
case stdAc::fanspeed_t::kMin:
case stdAc::fanspeed_t::kLow: return kHitachiAc264FanMin;
case stdAc::fanspeed_t::kMedium: return kHitachiAc264FanMedium;
case stdAc::fanspeed_t::kHigh:
case stdAc::fanspeed_t::kMax: return kHitachiAc424FanHigh;
default: return kHitachiAc424FanAuto;
}
}

/// Convert a native fan speed into its stdAc equivalent.
/// @param[in] speed The native setting to be converted.
/// @return The stdAc equivalent of the native setting.
stdAc::fanspeed_t IRHitachiAc264::toCommonFanSpeed(const uint8_t speed) const {
switch (speed) {
case kHitachiAc264FanHigh: return stdAc::fanspeed_t::kHigh;
case kHitachiAc264FanMedium: return stdAc::fanspeed_t::kMedium;
case kHitachiAc264FanMin: return stdAc::fanspeed_t::kMin;
default: return stdAc::fanspeed_t::kAuto;
}
}

/// Convert the current internal state into its stdAc::state_t equivalent.
/// @return The stdAc equivalent of the native settings.
stdAc::state_t IRHitachiAc264::toCommon(void) const {
stdAc::state_t result = IRHitachiAc424::toCommon();
result.protocol = decode_type_t::HITACHI_AC264;
result.swingv = stdAc::swingv_t::kOff;
return result;
}

/// Convert the internal state into a human readable string.
/// @return A string containing the settings in human-readable form.
String IRHitachiAc264::toString(void) const {
String result;
result.reserve(120); // Reserve some heap for the string to reduce fragging.
result += _toString();
return result;
}

#if DECODE_HITACHI_AC264
// For Decoding HITACHI_AC264, see `decodeHitachiAC`
#endif // DECODE_HITACHI_AC264
83 changes: 76 additions & 7 deletions src/ir_Hitachi.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ union Hitachi424Protocol{
// Byte 26
uint8_t :8;
// Byte 27
uint8_t Power :8;
uint8_t :4;
uint8_t Power :1;
uint8_t :3;
// Byte 28~34
uint8_t pad2[7];
// Byte 35
Expand Down Expand Up @@ -163,9 +165,6 @@ const uint8_t kHitachiAc344FanHigh = kHitachiAc424FanHigh;
const uint8_t kHitachiAc344FanAuto = kHitachiAc424FanAuto;
const uint8_t kHitachiAc344FanMax = kHitachiAc424FanMax;

const uint8_t kHitachiAc424PowerOn = 0xF1;
const uint8_t kHitachiAc424PowerOff = 0xE1;

const uint8_t kHitachiAc344SwingHAuto = 0; // 0b000
const uint8_t kHitachiAc344SwingHRightMax = 1; // 0b001
const uint8_t kHitachiAc344SwingHRight = 2; // 0b010
Expand Down Expand Up @@ -243,6 +242,57 @@ const uint8_t kHitachiAc1Sleep4 = 0b100;
const uint8_t kHitachiAc1ChecksumStartByte = 5;


/// Native representation of a Hitachi 164-bit A/C message.
union HitachiAC264Protocol{
uint8_t raw[kHitachiAc264StateLength]; ///< The state in native code.
struct {
// Bytes 0~10
uint8_t pad0[11];
// Byte 11
uint8_t Button :8;
// Byte 12
uint8_t :8;
// Byte 13
uint8_t :2;
uint8_t Temp :6;
// Byte 14
uint8_t :8;
// Bytes 14~24
uint8_t pad1[10];
// Byte 25
uint8_t Mode :4;
uint8_t Fan :4;
// Byte 26
uint8_t :8;
// Byte 27
uint8_t :4;
uint8_t Power :1;
uint8_t :3;
// Byte 28
uint8_t :8;
// Bytes 29~32
uint8_t pad2[4];
};
};

// HitachiAc264
const uint8_t kHitachiAc264ButtonPowerMode = kHitachiAc424ButtonPowerMode;
const uint8_t kHitachiAc264ButtonFan = kHitachiAc424ButtonFan;
const uint8_t kHitachiAc264ButtonTempDown = kHitachiAc424ButtonTempDown;
const uint8_t kHitachiAc264ButtonTempUp = kHitachiAc424ButtonTempUp;
const uint8_t kHitachiAc264ButtonSwingV = kHitachiAc424ButtonSwingV;
const uint8_t kHitachiAc264MinTemp = kHitachiAc424MinTemp; // 16C
const uint8_t kHitachiAc264MaxTemp = kHitachiAc424MaxTemp; // 32C
const uint8_t kHitachiAc264Fan = kHitachiAc424Fan;
const uint8_t kHitachiAc264Cool = kHitachiAc424Cool;
const uint8_t kHitachiAc264Dry = kHitachiAc424Dry;
const uint8_t kHitachiAc264Heat = kHitachiAc424Heat;
const uint8_t kHitachiAc264FanMin = kHitachiAc424FanMin;
const uint8_t kHitachiAc264FanLow = kHitachiAc424FanMin;
const uint8_t kHitachiAc264FanMedium = kHitachiAc424FanMedium;
const uint8_t kHitachiAc264FanHigh = kHitachiAc424FanHigh;
const uint8_t kHitachiAc264FanAuto = kHitachiAc424FanAuto;

// Classes
/// Class for handling detailed Hitachi 224-bit A/C messages.
/// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp
Expand Down Expand Up @@ -372,6 +422,7 @@ class IRHitachiAc1 {

/// Class for handling detailed Hitachi 53-byte/424-bit A/C messages.
class IRHitachiAc424 {
friend class IRHitachiAc264;
friend class IRHitachiAc344;
public:
explicit IRHitachiAc424(const uint16_t pin, const bool inverted = false,
Expand All @@ -392,7 +443,7 @@ class IRHitachiAc424 {
bool getPower(void) const;
void setTemp(const uint8_t temp, bool setPrevious = true);
uint8_t getTemp(void) const;
void setFan(const uint8_t speed);
virtual void setFan(const uint8_t speed);
uint8_t getFan(void) const;
uint8_t getButton(void) const;
void setButton(const uint8_t button);
Expand All @@ -404,9 +455,9 @@ class IRHitachiAc424 {
virtual void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAc424StateLength);
static uint8_t convertMode(const stdAc::opmode_t mode);
static uint8_t convertFan(const stdAc::fanspeed_t speed);
virtual uint8_t convertFan(const stdAc::fanspeed_t speed) const;
static stdAc::opmode_t toCommonMode(const uint8_t mode);
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
virtual stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed) const;
virtual stdAc::state_t toCommon(void) const;
virtual String toString(void) const;
#ifndef UNIT_TEST
Expand Down Expand Up @@ -478,4 +529,22 @@ class IRHitachiAc344: public IRHitachiAc424 {
static stdAc::swingh_t toCommonSwingH(const uint8_t pos);
String toString(void) const override;
};

/// Class for handling detailed Hitachi 264-bit A/C messages.
class IRHitachiAc264: public IRHitachiAc424 {
public:
explicit IRHitachiAc264(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset(void) override;
void setRaw(const uint8_t new_code[],
const uint16_t length = kHitachiAc264StateLength) override;
void setFan(const uint8_t speed) override;
uint8_t convertFan(const stdAc::fanspeed_t speed) const override;
stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed) const override;
stdAc::state_t toCommon(void) const override;
#if SEND_HITACHI_AC264
void send(const uint16_t repeat = kHitachiAcDefaultRepeat) override;
#endif // SEND_HITACHI_AC264
String toString(void) const override;
};
#endif // IR_HITACHI_H_
Loading