Skip to content
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
8 changes: 6 additions & 2 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,9 +695,9 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (decodeSharp(results, offset)) return true;
#endif
#if DECODE_COOLIX
DPRINTLN("Attempting Coolix decode");
DPRINTLN("Attempting Coolix 24-bit decode");
if (decodeCOOLIX(results, offset)) return true;
#endif
#endif // DECODE_COOLIX
#if DECODE_NIKAI
DPRINTLN("Attempting Nikai decode");
if (decodeNikai(results, offset)) return true;
Expand Down Expand Up @@ -1047,6 +1047,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Airton decode");
if (decodeAirton(results, offset)) return true;
#endif // DECODE_AIRTON
#if DECODE_COOLIX48
DPRINTLN("Attempting Coolix 48-bit decode");
if (decodeCoolix48(results, offset)) return true;
#endif // DECODE_COOLIX48
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand Down
7 changes: 6 additions & 1 deletion src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,12 @@ class IRrecv {
bool decodeCOOLIX(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kCoolixBits,
const bool strict = true);
#endif
#endif // DECODE_COOLIX
#if DECODE_COOLIX48
bool decodeCoolix48(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kCoolix48Bits,
const bool strict = true);
#endif // DECODE_COOLIX48
#if DECODE_DENON
bool decodeDenon(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kDenonBits,
Expand Down
11 changes: 10 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@
#define SEND_COOLIX _IR_ENABLE_DEFAULT_
#endif // SEND_COOLIX

#ifndef DECODE_COOLIX48
#define DECODE_COOLIX48 _IR_ENABLE_DEFAULT_
#endif // DECODE_COOLIX48
#ifndef SEND_COOLIX48
#define SEND_COOLIX48 _IR_ENABLE_DEFAULT_
#endif // SEND_COOLIX48

#ifndef DECODE_GLOBALCACHE
#define DECODE_GLOBALCACHE false // Not applicable.
#endif // DECODE_GLOBALCACHE
Expand Down Expand Up @@ -975,8 +982,9 @@ enum decode_type_t {
ARRIS,
RHOSS,
AIRTON,
COOLIX48, // 110
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = AIRTON,
kLastDecodeType = COOLIX48,
};

// Message lengths & required repeat values
Expand All @@ -998,6 +1006,7 @@ const uint16_t kArgoBits = kArgoStateLength * 8;
const uint16_t kArgoDefaultRepeat = kNoRepeat;
const uint16_t kArrisBits = 32;
const uint16_t kCoolixBits = 24;
const uint16_t kCoolix48Bits = kCoolixBits * 2;
const uint16_t kCoolixDefaultRepeat = kSingleRepeat;
const uint16_t kCarrierAcBits = 32;
const uint16_t kCarrierAcMinRepeat = kNoRepeat;
Expand Down
9 changes: 8 additions & 1 deletion src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
case AIWA_RC_T501:
case AMCOR:
case COOLIX:
case COOLIX48:
case ELITESCREENS:
case GICABLE:
case INAX:
Expand Down Expand Up @@ -661,6 +662,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kDoshishaBits; // 40
case SANYO_LC7461:
return kSanyoLC7461Bits; // 42
case COOLIX48:
case GOODWEATHER:
case KELON:
case MIDEA:
Expand Down Expand Up @@ -829,7 +831,12 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
case COOLIX:
sendCOOLIX(data, nbits, min_repeat);
break;
#endif
#endif // SEND_COOLIX
#if SEND_COOLIX48
case COOLIX48:
sendCoolix48(data, nbits, min_repeat);
break;
#endif // SEND_COOLIX48
#if SEND_DAIKIN64
case DAIKIN64:
sendDaikin64(data, nbits, min_repeat);
Expand Down
10 changes: 7 additions & 3 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,13 @@ class IRsend {
uint16_t repeat = kNoRepeat);
#endif
#if SEND_COOLIX
void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits,
uint16_t repeat = kCoolixDefaultRepeat);
#endif
void sendCOOLIX(const uint64_t data, const uint16_t nbits = kCoolixBits,
const uint16_t repeat = kCoolixDefaultRepeat);
#endif // SEND_COOLIX
#if SEND_COOLIX48
void sendCoolix48(const uint64_t data, const uint16_t nbits = kCoolix48Bits,
const uint16_t repeat = kCoolixDefaultRepeat);
#endif // SEND_COOLIX48
#if SEND_WHYNTER
void sendWhynter(const uint64_t data, const uint16_t nbits = kWhynterBits,
const uint16_t repeat = kNoRepeat);
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_ARRIS "\x0"
D_STR_RHOSS "\x0"
D_STR_AIRTON "\x0"
D_STR_COOLIX48 "\x0"
///< New protocol strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
72 changes: 64 additions & 8 deletions src/ir_Coolix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@
// pulse parameters in usec
const uint16_t kCoolixTick = 276; // Approximately 10.5 cycles at 38kHz
const uint16_t kCoolixBitMarkTicks = 2;
const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick;
const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; // 552us
const uint16_t kCoolixOneSpaceTicks = 6;
const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick;
const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; // 1656us
const uint16_t kCoolixZeroSpaceTicks = 2;
const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick;
const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; // 552us
const uint16_t kCoolixHdrMarkTicks = 17;
const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick;
const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; // 4692us
const uint16_t kCoolixHdrSpaceTicks = 16;
const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick;
const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; // 4416us
const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks;
const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick;
const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; // 5244us
const uint8_t kCoolix48ExtraTolerance = 5; // Percent

using irutils::addBoolToString;
using irutils::addIntToString;
Expand All @@ -40,7 +41,7 @@ using irutils::addModeToString;
using irutils::addTempToString;

#if SEND_COOLIX
/// Send a Coolix message
/// Send a Coolix 24-bit message
/// Status: STABLE / Confirmed Working.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
Expand Down Expand Up @@ -620,7 +621,7 @@ String IRCoolixAC::toString(void) const {
}

#if DECODE_COOLIX
/// Decode the supplied Coolix A/C message.
/// Decode the supplied Coolix 24-bit A/C message.
/// Status: STABLE / Known Working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
Expand Down Expand Up @@ -699,3 +700,58 @@ bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t offset,
return true;
}
#endif // DECODE_COOLIX

#if SEND_COOLIX48
/// Send a Coolix 48-bit message.
/// Status: ALPHA / Untested.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694
/// @note This is effectively the same as `sendCOOLIX()` except requiring the
/// bit flipping be done prior to the call.
void IRsend::sendCoolix48(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
// Header + Data + Footer
sendGeneric(kCoolixHdrMark, kCoolixHdrSpace,
kCoolixBitMark, kCoolixOneSpace,
kCoolixBitMark, kCoolixZeroSpace,
kCoolixBitMark, kCoolixMinGap,
data, nbits, 38000, true, repeat, 33);
}
#endif // SEND_COOLIX48

#if DECODE_COOLIX
/// Decode the supplied Coolix 48-bit A/C message.
/// Status: BETA / Probably Working.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// result.
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694
bool IRrecv::decodeCoolix48(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kCoolix48Bits)
return false; // Not strictly a COOLIX48 message.

// Header + Data + Footer
if (!matchGeneric(results->rawbuf + offset, &(results->value),
results->rawlen - offset, nbits,
kCoolixHdrMark, kCoolixHdrSpace,
kCoolixBitMark, kCoolixOneSpace,
kCoolixBitMark, kCoolixZeroSpace,
kCoolixBitMark, kCoolixMinGap,
true, _tolerance + kCoolix48ExtraTolerance, 0, true))
return false;

// Success
results->decode_type = COOLIX48;
results->bits = nbits;
results->address = 0;
results->command = 0;
return true;
}
#endif // DECODE_COOLIX48
4 changes: 4 additions & 0 deletions src/ir_Coolix.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
/// @note Kudos:
/// Hamper: For the breakdown and mapping of the bit values.
/// fraschizzato: For additional ZoneFollow & SwingVStep analysis.
/// @note Timers seem to use the `COOLIX48` protocol.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1694

// Supports:
// Brand: Beko, Model: RG57K7(B)/BGEF Remote
Expand All @@ -21,6 +23,8 @@
// Brand: Toshiba, Model: RAS-M13YKV-E A/C
// Brand: Toshiba, Model: RAS-4M27YAV-E A/C
// Brand: Toshiba, Model: WH-E1YE remote
// Brand: Bosch, Model: RG36B4/BGE remote
// Brand: Bosch, Model: B1ZAI2441W/B1ZAO2441W A/C

#ifndef IR_COOLIX_H_
#define IR_COOLIX_H_
Expand Down
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_COOLIX
#define D_STR_COOLIX "COOLIX"
#endif // D_STR_COOLIX
#ifndef D_STR_COOLIX48
#define D_STR_COOLIX48 D_STR_COOLIX "48"
#endif // D_STR_COOLIX48
#ifndef D_STR_CORONA_AC
#define D_STR_CORONA_AC "CORONA_AC"
#endif // D_STR_CORONA_AC
Expand Down
92 changes: 92 additions & 0 deletions test/ir_Coolix_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@
#include "IRsend_test.h"
#include "gtest/gtest.h"


TEST(TestUtils, Housekeeping) {
// COOLIX
ASSERT_EQ("COOLIX", typeToString(decode_type_t::COOLIX));
ASSERT_EQ(decode_type_t::COOLIX, strToDecodeType("COOLIX"));
ASSERT_FALSE(hasACState(decode_type_t::COOLIX));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::COOLIX));
ASSERT_EQ(kCoolixBits, IRsend::defaultBits(decode_type_t::COOLIX));
ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX));

// COOLIX48
ASSERT_EQ("COOLIX48", typeToString(decode_type_t::COOLIX48));
ASSERT_EQ(decode_type_t::COOLIX48, strToDecodeType("COOLIX48"));
ASSERT_FALSE(hasACState(decode_type_t::COOLIX48));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::COOLIX48));
ASSERT_EQ(kCoolix48Bits, IRsend::defaultBits(decode_type_t::COOLIX48));
ASSERT_EQ(kSingleRepeat, IRsend::minRepeats(decode_type_t::COOLIX48));
}

// Tests for sendCOOLIX().

// Test sending typical data only.
Expand Down Expand Up @@ -941,3 +960,76 @@ TEST(TestCoolixACClass, VerifyZoneFollowFan) {
"Zone Follow: On, Sensor Temp: 19C",
ac.toString());
}

TEST(TestDecodeCoolix48, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);

// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1694#issue-1068786691
// Off Timer: 1 hour
const uint16_t rawData[199] = {
4342, 4454, 486, 1724, 436, 658, 438, 1748, 464, 1718, 462, 634, 440, 656,
462, 1696, 488, 634, 462, 634, 436, 1722, 516, 608, 462, 660, 436, 1694,
488, 1720, 440, 630, 488, 1700, 488, 1704, 458, 660, 462, 1698, 490, 632,
462, 634, 436, 684, 436, 1700, 464, 1748, 462, 634, 462, 1720, 436, 658,
462, 1700, 488, 1692, 512, 1696, 438, 684, 410, 686, 434, 688, 408, 1696,
488, 1694, 464, 682, 414, 1748, 436, 1722, 488, 632, 438, 686, 408, 662,
462, 1696, 488, 1722, 462, 1696, 462, 1746, 436, 1798, 386, 1694, 490,
1720, 516, 5234, 4370, 4446, 490, 1690, 492, 658, 434, 1726, 436, 1746,
464, 604, 488, 658, 412, 1718, 490, 636, 460, 660, 438, 1698, 460, 662,
458, 632, 436, 1718, 490, 1720, 488, 608, 436, 1754, 462, 1726, 438, 682,
414, 1748, 464, 632, 460, 660, 410, 658, 438, 1748, 464, 1694, 464, 660,
436, 1720, 488, 634, 460, 1726, 462, 1724, 462, 1692, 490, 606, 462, 714,
384, 660, 460, 1722, 460, 1722, 490, 606, 464, 1718, 490, 1670, 486, 634,
462, 662, 410, 660, 460, 1722, 464, 1718, 460, 1696, 464, 1720, 462, 1720,
462, 1722, 486, 1700, 462}; // UNKNOWN 1F691B97

irsend.begin();
irsend.reset();

irsend.sendRaw(rawData, 199, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(COOLIX48, irsend.capture.decode_type);
EXPECT_EQ(kCoolix48Bits, irsend.capture.bits);
EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
}

TEST(TestDecodeCoolix48, SyntheticSelfDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendCoolix48(0xB24DA35C6C7F);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(COOLIX48, irsend.capture.decode_type);
EXPECT_EQ(kCoolix48Bits, irsend.capture.bits);
EXPECT_EQ(0xB24DA35C6C7F, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);

EXPECT_EQ(
"f38000d33"
"m4692s4416" // Message.
"m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552"
"m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656"
"m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656"
"m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552"
"m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552"
"m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656"
"m552s5244"
"m4692s4416" // Repeat
"m552s1656m552s552m552s1656m552s1656m552s552m552s552m552s1656m552s552"
"m552s552m552s1656m552s552m552s552m552s1656m552s1656m552s552m552s1656"
"m552s1656m552s552m552s1656m552s552m552s552m552s552m552s1656m552s1656"
"m552s552m552s1656m552s552m552s1656m552s1656m552s1656m552s552m552s552"
"m552s552m552s1656m552s1656m552s552m552s1656m552s1656m552s552m552s552"
"m552s552m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656m552s1656"
"m552s5244",
irsend.outputStr());
}