mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
Experimental basic support for Sanyo AC 152 bit protocol. (#1828)
* LSBF order determined by sequencing a temperature range. * add `sendSanyoAc152()` & `decodeSanyoAc152()` routines * Fix some comments. * Unit test coverage added for new protocol. * Update supported devices info. For #1826
This commit is contained in:
@@ -1132,6 +1132,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
||||
DPRINTLN("Attempting TCL AC 96-bit decode");
|
||||
if (decodeTcl96Ac(results, offset)) return true;
|
||||
#endif // DECODE_TCL96AC
|
||||
#if DECODE_SANYO_AC152
|
||||
DPRINTLN("Attempting Sanyo AC 152-bit decode");
|
||||
if (decodeSanyoAc152(results, offset)) return true;
|
||||
#endif // DECODE_SANYO_AC152
|
||||
// Typically new protocols are added above this line.
|
||||
}
|
||||
#if DECODE_HASH
|
||||
|
||||
@@ -325,6 +325,12 @@ class IRrecv {
|
||||
const uint16_t nbits = kSanyoAc88Bits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_SANYO_AC88
|
||||
#if DECODE_SANYO_AC152
|
||||
bool decodeSanyoAc152(decode_results *results,
|
||||
uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kSanyoAc152Bits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_SANYO_AC152
|
||||
#if DECODE_MITSUBISHI
|
||||
bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kMitsubishiBits,
|
||||
|
||||
@@ -238,6 +238,13 @@
|
||||
#define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_SANYO_AC88
|
||||
|
||||
#ifndef DECODE_SANYO_AC152
|
||||
#define DECODE_SANYO_AC152 _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_SANYO_AC152
|
||||
#ifndef SEND_SANYO_AC152
|
||||
#define SEND_SANYO_AC152 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_SANYO_AC152
|
||||
|
||||
#ifndef DECODE_MITSUBISHI
|
||||
#define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_MITSUBISHI
|
||||
@@ -927,7 +934,7 @@
|
||||
DECODE_SANYO_AC88 || DECODE_RHOSS || DECODE_HITACHI_AC264 || \
|
||||
DECODE_KELON168 || DECODE_HITACHI_AC296 || DECODE_CARRIER_AC128 || \
|
||||
DECODE_DAIKIN200 || DECODE_HAIER_AC160 || DECODE_TCL96AC || \
|
||||
DECODE_BOSCH144 || \
|
||||
DECODE_BOSCH144 || DECODE_SANYO_AC152 || \
|
||||
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
|
||||
@@ -1088,8 +1095,9 @@ enum decode_type_t {
|
||||
CLIMABUTLER,
|
||||
TCL96AC,
|
||||
BOSCH144, // 120
|
||||
SANYO_AC152,
|
||||
// Add new entries before this one, and update it to point to the last entry.
|
||||
kLastDecodeType = BOSCH144,
|
||||
kLastDecodeType = SANYO_AC152,
|
||||
};
|
||||
|
||||
// Message lengths & required repeat values
|
||||
@@ -1299,6 +1307,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 kSanyoAc152StateLength = 19;
|
||||
const uint16_t kSanyoAc152Bits = kSanyoAc152StateLength * 8;
|
||||
const uint16_t kSanyoAc152MinRepeat = kNoRepeat;
|
||||
const uint16_t kSanyoSA8650BBits = 12;
|
||||
const uint16_t kSanyoLC7461AddressBits = 13;
|
||||
const uint16_t kSanyoLC7461CommandBits = 8;
|
||||
|
||||
@@ -768,6 +768,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
|
||||
return kSanyoAcBits;
|
||||
case SANYO_AC88:
|
||||
return kSanyoAc88Bits;
|
||||
case SANYO_AC152:
|
||||
return kSanyoAc152Bits;
|
||||
case SHARP_AC:
|
||||
return kSharpAcBits;
|
||||
case TCL96AC:
|
||||
@@ -1353,6 +1355,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
|
||||
sendSanyoAc88(state, nbytes);
|
||||
break;
|
||||
#endif // SEND_SANYO_AC88
|
||||
#if SEND_SANYO_AC152
|
||||
case SANYO_AC152:
|
||||
sendSanyoAc152(state, nbytes);
|
||||
break;
|
||||
#endif // SEND_SANYO_AC152
|
||||
#if SEND_SHARP_AC
|
||||
case SHARP_AC:
|
||||
sendSharpAc(state, nbytes);
|
||||
|
||||
@@ -346,6 +346,11 @@ class IRsend {
|
||||
const uint16_t nbytes = kSanyoAc88StateLength,
|
||||
const uint16_t repeat = kSanyoAc88MinRepeat);
|
||||
#endif // SEND_SANYO_AC88
|
||||
#if SEND_SANYO_AC152
|
||||
void sendSanyoAc152(const uint8_t *data,
|
||||
const uint16_t nbytes = kSanyoAc152StateLength,
|
||||
const uint16_t repeat = kSanyoAc152MinRepeat);
|
||||
#endif // SEND_SANYO_AC152
|
||||
#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)
|
||||
|
||||
@@ -404,6 +404,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
|
||||
D_STR_CLIMABUTLER "\x0"
|
||||
D_STR_TCL96AC "\x0"
|
||||
D_STR_BOSCH144 "\x0"
|
||||
D_STR_SANYO_AC152 "\x0"
|
||||
///< New protocol strings should be added just above this line.
|
||||
"\x0" ///< This string requires double null termination.
|
||||
};
|
||||
|
||||
@@ -213,6 +213,7 @@ bool hasACState(const decode_type_t protocol) {
|
||||
case SAMSUNG_AC:
|
||||
case SANYO_AC:
|
||||
case SANYO_AC88:
|
||||
case SANYO_AC152:
|
||||
case SHARP_AC:
|
||||
case TCL96AC:
|
||||
case TCL112AC:
|
||||
|
||||
@@ -77,6 +77,14 @@ const uint32_t kSanyoAc88Gap = 3675; ///< uSeconds
|
||||
const uint16_t kSanyoAc88Freq = 38000; ///< Hz. (Guess only)
|
||||
const uint8_t kSanyoAc88ExtraTolerance = 5; /// (%) Extra tolerance to use.
|
||||
|
||||
const uint16_t kSanyoAc152HdrMark = 3300; ///< uSeconds
|
||||
const uint16_t kSanyoAc152BitMark = 440; ///< uSeconds
|
||||
const uint16_t kSanyoAc152HdrSpace = 1725; ///< uSeconds
|
||||
const uint16_t kSanyoAc152OneSpace = 1290; ///< uSeconds
|
||||
const uint16_t kSanyoAc152ZeroSpace = 405; ///< uSeconds
|
||||
const uint16_t kSanyoAc152Freq = 38000; ///< Hz. (Guess only)
|
||||
const uint8_t kSanyoAc152ExtraTolerance = 13; /// (%) Extra tolerance to use.
|
||||
|
||||
#if SEND_SANYO
|
||||
/// Construct a Sanyo LC7461 message.
|
||||
/// @param[in] address The 13 bit value of the address(Custom) portion of the
|
||||
@@ -687,7 +695,7 @@ void IRsend::sendSanyoAc88(const uint8_t data[], const uint16_t nbytes,
|
||||
#endif // SEND_SANYO_AC88
|
||||
|
||||
#if DECODE_SANYO_AC88
|
||||
/// Decode the supplied SanyoAc message.
|
||||
/// Decode the supplied SanyoAc88 message.
|
||||
/// Status: ALPHA / Untested.
|
||||
/// @param[in,out] results Ptr to the data to decode & where to store the decode
|
||||
/// @warning data's bit order may change. It is not yet confirmed.
|
||||
@@ -976,3 +984,61 @@ String IRSanyoAc88::toString(void) const {
|
||||
result += addLabeledString(minsToString(getClock()), kClockStr);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SEND_SANYO_AC152
|
||||
/// Send a SanyoAc152 formatted message.
|
||||
/// Status: BETA / Probably works.
|
||||
/// @param[in] data An array of bytes containing the IR command.
|
||||
/// @warning data's bit order may change. It is not yet confirmed.
|
||||
/// @param[in] nbytes Nr. of bytes of data in the array.
|
||||
/// @param[in] repeat Nr. of times the message is to be repeated.
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826
|
||||
void IRsend::sendSanyoAc152(const uint8_t data[], const uint16_t nbytes,
|
||||
const uint16_t repeat) {
|
||||
// (Header + Data + Footer) per repeat
|
||||
sendGeneric(kSanyoAc152HdrMark, kSanyoAc152HdrSpace,
|
||||
kSanyoAc152BitMark, kSanyoAc152OneSpace,
|
||||
kSanyoAc152BitMark, kSanyoAc152ZeroSpace,
|
||||
kSanyoAc152BitMark, kDefaultMessageGap,
|
||||
data, nbytes, kSanyoAc152Freq, false, repeat, kDutyDefault);
|
||||
space(kDefaultMessageGap); // Make a guess at a post message gap.
|
||||
}
|
||||
#endif // SEND_SANYO_AC152
|
||||
|
||||
#if DECODE_SANYO_AC152
|
||||
/// Decode the supplied SanyoAc152 message.
|
||||
/// Status: BETA / Probably works.
|
||||
/// @param[in,out] results Ptr to the data to decode & where to store the decode
|
||||
/// @warning data's bit order may change. It is not yet confirmed.
|
||||
/// @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/1503
|
||||
bool IRrecv::decodeSanyoAc152(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits, const bool strict) {
|
||||
if (strict && nbits != kSanyoAc152Bits)
|
||||
return false;
|
||||
|
||||
// Header + Data + Footer
|
||||
if (!matchGeneric(results->rawbuf + offset, results->state,
|
||||
results->rawlen - offset, nbits,
|
||||
kSanyoAc152HdrMark, kSanyoAc152HdrSpace,
|
||||
kSanyoAc152BitMark, kSanyoAc152OneSpace,
|
||||
kSanyoAc152BitMark, kSanyoAc152ZeroSpace,
|
||||
kSanyoAc152BitMark,
|
||||
kDefaultMessageGap, // Just a guess.
|
||||
false, _tolerance + kSanyoAc152ExtraTolerance,
|
||||
kMarkExcess, false))
|
||||
return false; // No match!
|
||||
|
||||
// Success
|
||||
results->decode_type = decode_type_t::SANYO_AC152;
|
||||
results->bits = nbits;
|
||||
// No need to record the state as we stored it as we decoded it.
|
||||
// As we use result->state, we don't record value, address, or command as it
|
||||
// is a union data type.
|
||||
return true;
|
||||
}
|
||||
#endif // DECODE_SANYO_AC152
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
/// @see https://docs.google.com/spreadsheets/d/1dYfLsnYvpjV-SgO8pdinpfuBIpSzm8Q1R5SabrLeskw/edit?usp=sharing
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503
|
||||
/// @see https://docs.google.com/spreadsheets/d/1weUmGAsEpfX38gg5rlDN69Uchnbr6gQl9FqHffLBIRk/edit#gid=0
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1826
|
||||
|
||||
// Supports:
|
||||
// Brand: Sanyo, Model: SA 8650B - disabled
|
||||
@@ -21,6 +22,8 @@
|
||||
// Brand: Sanyo, Model: RCS-2HS4E remote (SANYO_AC)
|
||||
// Brand: Sanyo, Model: SAP-K242AH A/C (SANYO_AC)
|
||||
// Brand: Sanyo, Model: RCS-2S4E remote (SANYO_AC)
|
||||
// Brand: Sanyo, Model: RCS-4MHVPIS4EE remote (SANYO_AC152)
|
||||
// Brand: Sanyo, Model: SAP-KMRV124EHE A/C (SANYO_AC152)
|
||||
|
||||
#ifndef IR_SANYO_H_
|
||||
#define IR_SANYO_H_
|
||||
|
||||
@@ -980,13 +980,16 @@ D_STR_INDIRECT " " D_STR_MODE
|
||||
#define D_STR_SANYO "SANYO"
|
||||
#endif // D_STR_SANYO
|
||||
#ifndef D_STR_SANYO_AC
|
||||
#define D_STR_SANYO_AC "SANYO_AC"
|
||||
#define D_STR_SANYO_AC D_STR_SANYO "_AC"
|
||||
#endif // D_STR_SANYO_AC
|
||||
#ifndef D_STR_SANYO_AC88
|
||||
#define D_STR_SANYO_AC88 "SANYO_AC88"
|
||||
#define D_STR_SANYO_AC88 D_STR_SANYO_AC "88"
|
||||
#endif // D_STR_SANYO_AC88
|
||||
#ifndef D_STR_SANYO_AC152
|
||||
#define D_STR_SANYO_AC152 D_STR_SANYO_AC "152"
|
||||
#endif // D_STR_SANYO_AC152
|
||||
#ifndef D_STR_SANYO_LC7461
|
||||
#define D_STR_SANYO_LC7461 "SANYO_LC7461"
|
||||
#define D_STR_SANYO_LC7461 D_STR_SANYO "_LC7461"
|
||||
#endif // D_STR_SANYO_LC7461
|
||||
#ifndef D_STR_SHARP
|
||||
#define D_STR_SHARP "SHARP"
|
||||
|
||||
@@ -284,6 +284,14 @@ TEST(TestUtils, Housekeeping) {
|
||||
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::SANYO_AC88));
|
||||
ASSERT_EQ(kSanyoAc88Bits, IRsend::defaultBits(decode_type_t::SANYO_AC88));
|
||||
ASSERT_EQ(kSanyoAc88MinRepeat, IRsend::minRepeats(decode_type_t::SANYO_AC88));
|
||||
// Sanyo A/C 152 Bit.
|
||||
ASSERT_EQ("SANYO_AC152", typeToString(decode_type_t::SANYO_AC152));
|
||||
ASSERT_EQ(decode_type_t::SANYO_AC152, strToDecodeType("SANYO_AC152"));
|
||||
ASSERT_TRUE(hasACState(decode_type_t::SANYO_AC152));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::SANYO_AC152));
|
||||
ASSERT_EQ(kSanyoAc152Bits, IRsend::defaultBits(decode_type_t::SANYO_AC152));
|
||||
ASSERT_EQ(kSanyoAc152MinRepeat,
|
||||
IRsend::minRepeats(decode_type_t::SANYO_AC152));
|
||||
}
|
||||
|
||||
TEST(TestDecodeSanyoAc, DecodeRealExamples) {
|
||||
@@ -820,3 +828,70 @@ TEST(TestSanyoAc88Class, Clock) {
|
||||
ac.setClock(25 * 60 + 61);
|
||||
EXPECT_EQ(23 * 60 + 59, ac.getClock());
|
||||
}
|
||||
|
||||
TEST(TestDecodeSanyoAc152, DecodeRealExamples) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
// Ref: "16c" from https://github.com/crankyoldgit/IRremoteESP8266/issues/1826#issuecomment-1160708653
|
||||
const uint16_t rawData[307] = {
|
||||
3294, 1726, 420, 330, 458, 462, 382, 452, 438, 330, 456, 458, 384, 454,
|
||||
384, 1312, 422, 324, 512, 336, 454, 458, 384, 450, 438, 358, 436, 464,
|
||||
424, 326, 458, 476, 372, 458, 430, 328, 458, 464, 382, 1308, 424, 326,
|
||||
510, 1264, 424, 268, 520, 460, 380, 460, 436, 324, 462, 400, 436, 474,
|
||||
372, 456, 430, 342, 452, 450, 388, 446, 442, 1262, 422, 266, 520, 1314,
|
||||
372, 1306, 424, 1258, 370, 390, 448, 1314, 372, 1310, 426, 308, 522, 338,
|
||||
454, 470, 370, 454, 438, 330, 456, 468, 370, 456, 384, 464, 384, 1306,
|
||||
422, 328, 460, 472, 374, 448, 442, 1258, 426, 1256, 426, 268, 520, 464,
|
||||
382, 460, 430, 328, 508, 1264, 426, 262, 572, 1262, 424, 228, 604, 1262,
|
||||
372, 1312, 372, 1310, 426, 1256, 422, 1258, 424, 262, 524, 418, 428, 456,
|
||||
382, 1308, 372, 456, 386, 456, 382, 464, 378, 1308, 424, 360, 436, 454,
|
||||
430, 344, 450, 1306, 372, 1310, 424, 326, 510, 338, 452, 456, 384, 456,
|
||||
436, 328, 510, 1258, 372, 1310, 422, 338, 454, 466, 424, 328, 460, 1310,
|
||||
372, 1312, 424, 1258, 450, 262, 496, 1310, 372, 1310, 426, 1260, 424, 260,
|
||||
526, 442, 442, 1264, 426, 268, 520, 458, 380, 450, 386, 462, 436, 320,
|
||||
518, 1256, 372, 394, 446, 398, 494, 334, 506, 326, 510, 276, 518, 460,
|
||||
430, 332, 508, 326, 510, 356, 440, 448, 444, 264, 572, 336, 456, 408, 434,
|
||||
454, 438, 332, 506, 336, 454, 460, 384, 448, 444, 326, 510, 332, 456, 442,
|
||||
400, 456, 384, 456, 386, 452, 388, 454, 440, 326, 512, 272, 518, 450, 440,
|
||||
334, 454, 458, 440, 320, 516, 268, 570, 340, 452, 468, 424, 260, 574, 336,
|
||||
456, 394, 444, 458, 438, 328, 508, 1258, 370, 1312, 372, 1312, 424, 314,
|
||||
468, 1312, 450, 1232, 370, 1314, 420, 324, 514}; // UNKNOWN 584FBE80
|
||||
|
||||
const uint8_t expectedState[kSanyoAc152StateLength] = {
|
||||
0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62,
|
||||
0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77};
|
||||
irsend.begin();
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 307, 38000);
|
||||
irsend.makeDecodeResult();
|
||||
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(SANYO_AC152, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_FALSE(irsend.capture.repeat);
|
||||
EXPECT_EQ(
|
||||
"",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
}
|
||||
|
||||
TEST(TestDecodeSanyoAc152, SyntheticSelfDecode) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
const uint8_t expectedState[kSanyoAc152StateLength] = {
|
||||
0x40, 0x00, 0x14, 0x80, 0x6E, 0x80, 0x18, 0xEA, 0x23, 0x62,
|
||||
0x30, 0xEE, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77};
|
||||
irsend.begin();
|
||||
irsend.reset();
|
||||
irsend.sendSanyoAc152(expectedState);
|
||||
irsend.makeDecodeResult();
|
||||
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(SANYO_AC152, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kSanyoAc152Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_FALSE(irsend.capture.repeat);
|
||||
EXPECT_EQ(
|
||||
"",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user