Skip to content

Commit

Permalink
HITACHI_AC264: Add minimal detailed support.
Browse files Browse the repository at this point in the history
* Supports Power, Temp, Mode, & Fanspeed. That's it.
  - Effectively a parent class of `IRHitachiAc424`.
* Add `IRac` integration.
* Update & add unit tests.

Fixes #1729
  • Loading branch information
crankyoldgit committed Jan 13, 2022
1 parent 9da665c commit d9357d9
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 18 deletions.
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

0 comments on commit d9357d9

Please sign in to comment.