Skip to content

Commit 89d039a

Browse files
authored
Detailed support for Tornado/Sanyo 88-bit A/C protocol (#1568)
* 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
1 parent 8eb5636 commit 89d039a

File tree

14 files changed

+889
-23
lines changed

14 files changed

+889
-23
lines changed

src/IRac.cpp

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
259259
#if SEND_SANYO_AC
260260
case decode_type_t::SANYO_AC:
261261
#endif
262+
#if SEND_SANYO_AC88
263+
case decode_type_t::SANYO_AC88:
264+
#endif
262265
#if SEND_SHARP_AC
263266
case decode_type_t::SHARP_AC:
264267
#endif
@@ -1766,7 +1769,7 @@ void IRac::samsung(IRSamsungAc *ac,
17661769
#endif // SEND_SAMSUNG_AC
17671770

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

1810+
#if SEND_SANYO_AC88
1811+
/// Send a Sanyo 88-bit A/C message with the supplied settings.
1812+
/// @param[in, out] ac A Ptr to an IRSanyoAc88 object to use.
1813+
/// @param[in] on The power setting.
1814+
/// @param[in] mode The operation mode setting.
1815+
/// @param[in] degrees The temperature setting in degrees.
1816+
/// @param[in] fan The speed setting for the fan.
1817+
/// @param[in] swingv The vertical swing setting.
1818+
/// @param[in] turbo Run the device in turbo/powerful mode.
1819+
/// @param[in] filter Turn on the (ion/pollen/etc) filter mode.
1820+
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
1821+
/// @param[in] clock The time in Nr. of mins since midnight. < 0 is ignore.
1822+
void IRac::sanyo88(IRSanyoAc88 *ac,
1823+
const bool on, const stdAc::opmode_t mode,
1824+
const float degrees, const stdAc::fanspeed_t fan,
1825+
const stdAc::swingv_t swingv, const bool turbo,
1826+
const bool filter, const int16_t sleep,
1827+
const int16_t clock) {
1828+
ac->begin();
1829+
ac->setPower(on);
1830+
ac->setMode(ac->convertMode(mode));
1831+
ac->setTemp(degrees);
1832+
ac->setFan(ac->convertFan(fan));
1833+
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
1834+
// No Horizontal swing setting available.
1835+
// No Quiet setting available.
1836+
ac->setTurbo(turbo);
1837+
// No Econo setting available.
1838+
// No Light setting available.
1839+
ac->setFilter(filter);
1840+
// No Clean setting available.
1841+
// No Beep setting available.
1842+
ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
1843+
if (clock >= 0) ac->setClock(clock);
1844+
ac->send();
1845+
}
1846+
#endif // SEND_SANYO_AC88
1847+
18071848
#if SEND_SHARP_AC
18081849
/// Send a Sharp A/C message with the supplied settings.
18091850
/// @note Multiple IR messages may be generated & sent.
@@ -2798,6 +2839,15 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
27982839
break;
27992840
}
28002841
#endif // SEND_SANYO_AC
2842+
#if SEND_SANYO_AC88
2843+
case SANYO_AC88:
2844+
{
2845+
IRSanyoAc88 ac(_pin, _inverted, _modulation);
2846+
sanyo88(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
2847+
send.turbo, send.filter, send.sleep, send.clock);
2848+
break;
2849+
}
2850+
#endif // SEND_SANYO_AC88
28012851
#if SEND_SHARP_AC
28022852
case SHARP_AC:
28032853
{
@@ -2912,7 +2962,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
29122962
return false; // Fail, didn't match anything.
29132963
}
29142964
return true; // Success.
2915-
}
2965+
} // NOLINT(readability/fn_size)
29162966

29172967
/// Update the previous state to the current one.
29182968
void IRac::markAsSent(void) {
@@ -3529,6 +3579,13 @@ namespace IRAcUtils {
35293579
return ac.toString();
35303580
}
35313581
#endif // DECODE_SANYO_AC
3582+
#if DECODE_SANYO_AC88
3583+
case decode_type_t::SANYO_AC88: {
3584+
IRSanyoAc88 ac(kGpioUnused);
3585+
ac.setRaw(result->state);
3586+
return ac.toString();
3587+
}
3588+
#endif // DECODE_SANYO_AC88
35323589
#if DECODE_SHARP_AC
35333590
case decode_type_t::SHARP_AC: {
35343591
IRSharpAc ac(kGpioUnused);
@@ -4006,6 +4063,14 @@ namespace IRAcUtils {
40064063
break;
40074064
}
40084065
#endif // DECODE_SANYO_AC
4066+
#if DECODE_SANYO_AC88
4067+
case decode_type_t::SANYO_AC88: {
4068+
IRSanyoAc88 ac(kGpioUnused);
4069+
ac.setRaw(decode->state);
4070+
*result = ac.toCommon();
4071+
break;
4072+
}
4073+
#endif // DECODE_SANYO_AC88
40094074
#if DECODE_SHARP_AC
40104075
case decode_type_t::SHARP_AC: {
40114076
IRSharpAc ac(kGpioUnused);

src/IRac.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,14 @@ void electra(IRElectraAc *ac,
393393
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
394394
const bool beep, const int16_t sleep = -1);
395395
#endif // SEND_SANYO_AC
396+
#if SEND_SANYO_AC88
397+
void sanyo88(IRSanyoAc88 *ac,
398+
const bool on, const stdAc::opmode_t mode,
399+
const float degrees, const stdAc::fanspeed_t fan,
400+
const stdAc::swingv_t swingv, const bool turbo,
401+
const bool filter,
402+
const int16_t sleep = -1, const int16_t clock = -1);
403+
#endif // SEND_SANYO_AC88
396404
#if SEND_SHARP_AC
397405
void sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model,
398406
const bool on, const bool prev_power, const stdAc::opmode_t mode,

src/IRrecv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
10281028
DPRINTLN("Attempting Kelon decode");
10291029
if (decodeKelon(results, offset)) return true;
10301030
#endif // DECODE_KELON
1031+
#if DECODE_SANYO_AC88
1032+
DPRINTLN("Attempting SanyoAc88 decode");
1033+
if (decodeSanyoAc88(results, offset)) return true;
1034+
#endif // DECODE_SANYO_AC88
10311035
// Typically new protocols are added above this line.
10321036
}
10331037
#if DECODE_HASH

src/IRrecv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ class IRrecv {
308308
const uint16_t nbits = kSanyoAcBits,
309309
const bool strict = true);
310310
#endif // DECODE_SANYO_AC
311+
#if DECODE_SANYO_AC88
312+
bool decodeSanyoAc88(decode_results *results,
313+
uint16_t offset = kStartOffset,
314+
const uint16_t nbits = kSanyoAc88Bits,
315+
const bool strict = true);
316+
#endif // DECODE_SANYO_AC88
311317
#if DECODE_MITSUBISHI
312318
bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset,
313319
const uint16_t nbits = kMitsubishiBits,

src/IRremoteESP8266.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@
209209
#define SEND_SANYO_AC _IR_ENABLE_DEFAULT_
210210
#endif // SEND_SANYO_AC
211211

212+
#ifndef DECODE_SANYO_AC88
213+
#define DECODE_SANYO_AC88 _IR_ENABLE_DEFAULT_
214+
#endif // DECODE_SANYO_AC88
215+
#ifndef SEND_SANYO_AC88
216+
#define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_
217+
#endif // SEND_SANYO_AC88
218+
212219
#ifndef DECODE_MITSUBISHI
213220
#define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_
214221
#endif // DECODE_MITSUBISHI
@@ -790,6 +797,7 @@
790797
DECODE_HITACHI_AC344 || DECODE_CORONA_AC || DECODE_SANYO_AC || \
791798
DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \
792799
DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \
800+
DECODE_SANYO_AC88 || \
793801
false)
794802
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
795803
// you might also want to add the protocol to hasACState function
@@ -934,8 +942,9 @@ enum decode_type_t {
934942
TEKNOPOINT,
935943
KELON,
936944
TROTEC_3550,
945+
SANYO_AC88, // 105
937946
// Add new entries before this one, and update it to point to the last entry.
938-
kLastDecodeType = TROTEC_3550,
947+
kLastDecodeType = SANYO_AC88,
939948
};
940949

941950
// Message lengths & required repeat values
@@ -1121,6 +1130,9 @@ const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8;
11211130
const uint16_t kSamsungAcDefaultRepeat = kNoRepeat;
11221131
const uint16_t kSanyoAcStateLength = 9;
11231132
const uint16_t kSanyoAcBits = kSanyoAcStateLength * 8;
1133+
const uint16_t kSanyoAc88StateLength = 11;
1134+
const uint16_t kSanyoAc88Bits = kSanyoAc88StateLength * 8;
1135+
const uint16_t kSanyoAc88MinRepeat = 2;
11241136
const uint16_t kSanyoSA8650BBits = 12;
11251137
const uint16_t kSanyoLC7461AddressBits = 13;
11261138
const uint16_t kSanyoLC7461CommandBits = 8;

src/IRsend.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
580580
return kDishMinRepeat;
581581
case EPSON:
582582
return kEpsonMinRepeat;
583+
case SANYO_AC88:
584+
return kSanyoAc88MinRepeat;
583585
case SONY:
584586
return kSonyMinRepeat;
585587
case SONY_38K:
@@ -739,6 +741,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
739741
return kSamsungAcBits;
740742
case SANYO_AC:
741743
return kSanyoAcBits;
744+
case SANYO_AC88:
745+
return kSanyoAc88Bits;
742746
case SHARP_AC:
743747
return kSharpAcBits;
744748
case TCL112AC:
@@ -1247,6 +1251,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
12471251
sendSanyoAc(state, nbytes);
12481252
break;
12491253
#endif // SEND_SANYO_AC
1254+
#if SEND_SANYO_AC88
1255+
case SANYO_AC88:
1256+
sendSanyoAc88(state, nbytes);
1257+
break;
1258+
#endif // SEND_SANYO_AC88
12501259
#if SEND_SHARP_AC
12511260
case SHARP_AC:
12521261
sendSharpAc(state, nbytes);

src/IRsend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@ class IRsend {
319319
const uint16_t nbytes = kSanyoAcStateLength,
320320
const uint16_t repeat = kNoRepeat);
321321
#endif // SEND_SANYO_AC
322+
#if SEND_SANYO_AC88
323+
void sendSanyoAc88(const uint8_t *data,
324+
const uint16_t nbytes = kSanyoAc88StateLength,
325+
const uint16_t repeat = kSanyoAc88MinRepeat);
326+
#endif // SEND_SANYO_AC88
322327
#if SEND_DISH
323328
// sendDISH() should typically be called with repeat=3 as DISH devices
324329
// expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes)

src/IRtext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,5 +290,6 @@ const PROGMEM char *kAllProtocolNamesStr =
290290
D_STR_TEKNOPOINT "\x0"
291291
D_STR_KELON "\x0"
292292
D_STR_TROTEC_3550 "\x0"
293+
D_STR_SANYO_AC88 "\x0"
293294
///< New protocol strings should be added just above this line.
294295
"\x0"; ///< This string requires double null termination.

src/IRutils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ bool hasACState(const decode_type_t protocol) {
177177
case PANASONIC_AC:
178178
case SAMSUNG_AC:
179179
case SANYO_AC:
180+
case SANYO_AC88:
180181
case SHARP_AC:
181182
case TCL112AC:
182183
case TEKNOPOINT:

0 commit comments

Comments
 (0)