Skip to content

Commit

Permalink
Detailed support for Tornado/Sanyo 88-bit A/C protocol (#1568)
Browse files Browse the repository at this point in the history
* Settings supported:
  - Power
  - Mode
  - Temp
  - Fan Speed
  - Sleep
  - Turbo
  - Filter
  - Clock
* Add support in `IRac` class.
* Unit tests added & updated.
* Other minor code cleanups.

Fixes #1503
  • Loading branch information
crankyoldgit authored Aug 16, 2021
1 parent 8eb5636 commit 89d039a
Show file tree
Hide file tree
Showing 14 changed files with 889 additions and 23 deletions.
69 changes: 67 additions & 2 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
#if SEND_SANYO_AC
case decode_type_t::SANYO_AC:
#endif
#if SEND_SANYO_AC88
case decode_type_t::SANYO_AC88:
#endif
#if SEND_SHARP_AC
case decode_type_t::SHARP_AC:
#endif
Expand Down Expand Up @@ -1766,7 +1769,7 @@ void IRac::samsung(IRSamsungAc *ac,
#endif // SEND_SAMSUNG_AC

#if SEND_SANYO_AC
/// Send a Toshiba A/C message with the supplied settings.
/// Send a Sanyo A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRSanyoAc object to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
Expand Down Expand Up @@ -1804,6 +1807,44 @@ void IRac::sanyo(IRSanyoAc *ac,
}
#endif // SEND_SANYO_AC

#if SEND_SANYO_AC88
/// Send a Sanyo 88-bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRSanyoAc88 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.
/// @param[in] swingv The vertical swing setting.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] filter Turn on the (ion/pollen/etc) filter mode.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
/// @param[in] clock The time in Nr. of mins since midnight. < 0 is ignore.
void IRac::sanyo88(IRSanyoAc88 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool turbo,
const bool filter, const int16_t sleep,
const int16_t clock) {
ac->begin();
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
// No Horizontal swing setting available.
// No Quiet setting available.
ac->setTurbo(turbo);
// No Econo setting available.
// No Light setting available.
ac->setFilter(filter);
// No Clean setting available.
// No Beep setting available.
ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
if (clock >= 0) ac->setClock(clock);
ac->send();
}
#endif // SEND_SANYO_AC88

#if SEND_SHARP_AC
/// Send a Sharp A/C message with the supplied settings.
/// @note Multiple IR messages may be generated & sent.
Expand Down Expand Up @@ -2798,6 +2839,15 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
}
#endif // SEND_SANYO_AC
#if SEND_SANYO_AC88
case SANYO_AC88:
{
IRSanyoAc88 ac(_pin, _inverted, _modulation);
sanyo88(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.turbo, send.filter, send.sleep, send.clock);
break;
}
#endif // SEND_SANYO_AC88
#if SEND_SHARP_AC
case SHARP_AC:
{
Expand Down Expand Up @@ -2912,7 +2962,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
return false; // Fail, didn't match anything.
}
return true; // Success.
}
} // NOLINT(readability/fn_size)

/// Update the previous state to the current one.
void IRac::markAsSent(void) {
Expand Down Expand Up @@ -3529,6 +3579,13 @@ namespace IRAcUtils {
return ac.toString();
}
#endif // DECODE_SANYO_AC
#if DECODE_SANYO_AC88
case decode_type_t::SANYO_AC88: {
IRSanyoAc88 ac(kGpioUnused);
ac.setRaw(result->state);
return ac.toString();
}
#endif // DECODE_SANYO_AC88
#if DECODE_SHARP_AC
case decode_type_t::SHARP_AC: {
IRSharpAc ac(kGpioUnused);
Expand Down Expand Up @@ -4006,6 +4063,14 @@ namespace IRAcUtils {
break;
}
#endif // DECODE_SANYO_AC
#if DECODE_SANYO_AC88
case decode_type_t::SANYO_AC88: {
IRSanyoAc88 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
break;
}
#endif // DECODE_SANYO_AC88
#if DECODE_SHARP_AC
case decode_type_t::SHARP_AC: {
IRSharpAc ac(kGpioUnused);
Expand Down
8 changes: 8 additions & 0 deletions src/IRac.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ void electra(IRElectraAc *ac,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool beep, const int16_t sleep = -1);
#endif // SEND_SANYO_AC
#if SEND_SANYO_AC88
void sanyo88(IRSanyoAc88 *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool turbo,
const bool filter,
const int16_t sleep = -1, const int16_t clock = -1);
#endif // SEND_SANYO_AC88
#if SEND_SHARP_AC
void sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model,
const bool on, const bool prev_power, const stdAc::opmode_t mode,
Expand Down
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Kelon decode");
if (decodeKelon(results, offset)) return true;
#endif // DECODE_KELON
#if DECODE_SANYO_AC88
DPRINTLN("Attempting SanyoAc88 decode");
if (decodeSanyoAc88(results, offset)) return true;
#endif // DECODE_SANYO_AC88
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand Down
6 changes: 6 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,12 @@ class IRrecv {
const uint16_t nbits = kSanyoAcBits,
const bool strict = true);
#endif // DECODE_SANYO_AC
#if DECODE_SANYO_AC88
bool decodeSanyoAc88(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kSanyoAc88Bits,
const bool strict = true);
#endif // DECODE_SANYO_AC88
#if DECODE_MITSUBISHI
bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kMitsubishiBits,
Expand Down
14 changes: 13 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,13 @@
#define SEND_SANYO_AC _IR_ENABLE_DEFAULT_
#endif // SEND_SANYO_AC

#ifndef DECODE_SANYO_AC88
#define DECODE_SANYO_AC88 _IR_ENABLE_DEFAULT_
#endif // DECODE_SANYO_AC88
#ifndef SEND_SANYO_AC88
#define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_
#endif // SEND_SANYO_AC88

#ifndef DECODE_MITSUBISHI
#define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_
#endif // DECODE_MITSUBISHI
Expand Down Expand Up @@ -790,6 +797,7 @@
DECODE_HITACHI_AC344 || DECODE_CORONA_AC || DECODE_SANYO_AC || \
DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \
DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \
DECODE_SANYO_AC88 || \
false)
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
// you might also want to add the protocol to hasACState function
Expand Down Expand Up @@ -934,8 +942,9 @@ enum decode_type_t {
TEKNOPOINT,
KELON,
TROTEC_3550,
SANYO_AC88, // 105
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = TROTEC_3550,
kLastDecodeType = SANYO_AC88,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1121,6 +1130,9 @@ const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8;
const uint16_t kSamsungAcDefaultRepeat = kNoRepeat;
const uint16_t kSanyoAcStateLength = 9;
const uint16_t kSanyoAcBits = kSanyoAcStateLength * 8;
const uint16_t kSanyoAc88StateLength = 11;
const uint16_t kSanyoAc88Bits = kSanyoAc88StateLength * 8;
const uint16_t kSanyoAc88MinRepeat = 2;
const uint16_t kSanyoSA8650BBits = 12;
const uint16_t kSanyoLC7461AddressBits = 13;
const uint16_t kSanyoLC7461CommandBits = 8;
Expand Down
9 changes: 9 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
return kDishMinRepeat;
case EPSON:
return kEpsonMinRepeat;
case SANYO_AC88:
return kSanyoAc88MinRepeat;
case SONY:
return kSonyMinRepeat;
case SONY_38K:
Expand Down Expand Up @@ -739,6 +741,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kSamsungAcBits;
case SANYO_AC:
return kSanyoAcBits;
case SANYO_AC88:
return kSanyoAc88Bits;
case SHARP_AC:
return kSharpAcBits;
case TCL112AC:
Expand Down Expand Up @@ -1247,6 +1251,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendSanyoAc(state, nbytes);
break;
#endif // SEND_SANYO_AC
#if SEND_SANYO_AC88
case SANYO_AC88:
sendSanyoAc88(state, nbytes);
break;
#endif // SEND_SANYO_AC88
#if SEND_SHARP_AC
case SHARP_AC:
sendSharpAc(state, nbytes);
Expand Down
5 changes: 5 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,11 @@ class IRsend {
const uint16_t nbytes = kSanyoAcStateLength,
const uint16_t repeat = kNoRepeat);
#endif // SEND_SANYO_AC
#if SEND_SANYO_AC88
void sendSanyoAc88(const uint8_t *data,
const uint16_t nbytes = kSanyoAc88StateLength,
const uint16_t repeat = kSanyoAc88MinRepeat);
#endif // SEND_SANYO_AC88
#if SEND_DISH
// sendDISH() should typically be called with repeat=3 as DISH devices
// expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes)
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,6 @@ const PROGMEM char *kAllProtocolNamesStr =
D_STR_TEKNOPOINT "\x0"
D_STR_KELON "\x0"
D_STR_TROTEC_3550 "\x0"
D_STR_SANYO_AC88 "\x0"
///< New protocol strings should be added just above this line.
"\x0"; ///< This string requires double null termination.
1 change: 1 addition & 0 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ bool hasACState(const decode_type_t protocol) {
case PANASONIC_AC:
case SAMSUNG_AC:
case SANYO_AC:
case SANYO_AC88:
case SHARP_AC:
case TCL112AC:
case TEKNOPOINT:
Expand Down
Loading

0 comments on commit 89d039a

Please sign in to comment.