Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor decodeMitsubishiAC() #1532

Merged
merged 2 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
142 changes: 32 additions & 110 deletions src/ir_Mitsubishi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,120 +257,42 @@ void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes,
bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t offset,
const uint16_t nbits,
const bool strict) {
if (results->rawlen <= ((kMitsubishiACBits * 2) + 2) + offset) {
DPRINTLN("Shorter than shortest possibly expected.");
return false; // Shorter than shortest possibly expected.
}
if (strict && nbits != kMitsubishiACBits) {
DPRINTLN("Request is out of spec.");
return false; // Request is out of spec.
// Compliance
if (strict && nbits != kMitsubishiACBits) return false; // Out of spec.
// Do we need to look for a repeat?
const uint16_t expected_repeats = strict ? kMitsubishiACMinRepeat : kNoRepeat;
// Enough data?
if (results->rawlen <= (nbits * 2 + kHeader + kFooter) *
(expected_repeats + 1) + offset - 1) return false;
// Handle repeats if we need too.
for (uint16_t r = 0; r <= expected_repeats; r++) {
// Header + Data + Footer
uint16_t used = matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, nbits,
kMitsubishiAcHdrMark, kMitsubishiAcHdrSpace,
kMitsubishiAcBitMark, kMitsubishiAcOneSpace,
kMitsubishiAcBitMark, kMitsubishiAcZeroSpace,
kMitsubishiAcRptMark, kMitsubishiAcRptSpace,
r < expected_repeats, // At least?
_tolerance + kMitsubishiAcExtraTolerance,
0, false);
if (!used) return false; // No match.
offset += used;
}
for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) results->state[i] = 0;
bool failure = false;
uint8_t rep = 0;
do {
failure = false;
// Header:
// Sometime happens that junk signals arrives before the real message
bool headerFound = false;
while (!headerFound &&
offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) {
headerFound =
matchMark(results->rawbuf[offset], kMitsubishiAcHdrMark) &&
matchSpace(results->rawbuf[offset + 1], kMitsubishiAcHdrSpace);
offset += 2;
}
if (!headerFound) {
DPRINTLN("Header mark not found.");
return false;
}
DPRINT("Header mark found at #");
DPRINTLN(offset - 2);
// Decode byte-by-byte:
match_result_t data_result;
for (uint8_t i = 0; i < kMitsubishiACStateLength && !failure; i++) {
results->state[i] = 0;
data_result =
matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark,
kMitsubishiAcOneSpace, kMitsubishiAcBitMark,
kMitsubishiAcZeroSpace,
_tolerance + kMitsubishiAcExtraTolerance, 0, false);
if (data_result.success == false) {
failure = true;
DPRINT("Byte decode failed at #");
DPRINTLN((uint16_t)i);
} else {
results->state[i] = data_result.data;
offset += data_result.used;
DPRINT((uint16_t)results->state[i]);
DPRINT(",");
}
DPRINTLN("");
}
// HEADER validation:
if (failure || results->state[0] != 0x23 || results->state[1] != 0xCB ||

// Compliance
if (strict) {
// Data signature check.
if (results->state[0] != 0x23 || results->state[1] != 0xCB ||
results->state[2] != 0x26 || results->state[3] != 0x01 ||
results->state[4] != 0x00) {
DPRINTLN("Header mismatch.");
failure = true;
} else {
// DATA part:

// FOOTER checksum:
if (!IRMitsubishiAC::validChecksum(results->state)) {
DPRINTLN("Checksum error.");
failure = true;
}
}
if (rep != kMitsubishiACMinRepeat && failure) {
bool repeatMarkFound = false;
while (!repeatMarkFound &&
offset < (results->rawlen - (kMitsubishiACBits * 2 + 4))) {
repeatMarkFound =
matchMark(results->rawbuf[offset], kMitsubishiAcRptMark) &&
matchSpace(results->rawbuf[offset + 1], kMitsubishiAcRptSpace);
offset += 2;
}
if (!repeatMarkFound) {
DPRINTLN("First attempt failure and repeat mark not found.");
return false;
}
}
rep++;
// Check if the repeat is correct if we need strict decode:
if (strict && !failure) {
DPRINTLN("Strict repeat check enabled.");
// Repeat mark and space:
if (!matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) ||
!matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace)) {
DPRINTLN("Repeat mark error.");
return false;
}
// Header mark and space:
if (!matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) ||
!matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace)) {
DPRINTLN("Repeat header error.");
return false;
}
// Payload:
for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) {
data_result =
matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark,
kMitsubishiAcOneSpace, kMitsubishiAcBitMark,
kMitsubishiAcZeroSpace,
_tolerance + kMitsubishiAcExtraTolerance, 0, false);
if (data_result.success == false ||
data_result.data != results->state[i]) {
DPRINTLN("Repeat payload error.");
return false;
}
offset += data_result.used;
}
} // strict repeat check
} while (failure && rep <= kMitsubishiACMinRepeat);
results->state[4] != 0x00) return false;
// Checksum
if (!IRMitsubishiAC::validChecksum(results->state)) return false;
}

results->decode_type = MITSUBISHI_AC;
results->bits = nbits;
return !failure;
return true;
}
#endif // DECODE_MITSUBISHI_AC

Expand Down
128 changes: 0 additions & 128 deletions test/ir_Mitsubishi_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -824,134 +824,6 @@ TEST(TestDecodeMitsubishiAC, DecodeRealExample) {
EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits);
}

// Tests for decodeMitsubishiAC() when the first payload has an error.
TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeeded) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
// Mitsubishi AC "Power On, 16C, low fan, vane auto move".
uint16_t rawData[583] = {
3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236,
440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394,
444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392,
446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390,
446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446,
392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390,
446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448,
390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438,
402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398,
// space 699 is not recognizable:
440, 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 699, 1260,
416, 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264,
422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400,
446, 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438,
400, 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400,
448, 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438,
400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398,
438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440,
398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398,
438, 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440,
398, 438, 1240, 444, 1264, 422, 390, 446, 392, 446, 1260, 414, 1268, 418,
1264, 422, 12984, 3478, 1708, 418, 1264, 422, 1234, 442, 398, 448, 390,
446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, 442, 1266, 420, 392,
444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, 416, 398, 440, 1266,
418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, 448, 392, 446, 1234,
440, 398, 450, 390, 446, 392, 444, 394, 444, 394, 442, 396, 442, 398, 440,
400, 438, 400, 448, 390, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398,
438, 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440,
398, 438, 400, 448, 416, 420, 392, 444, 1234, 440, 1240, 446, 394, 442,
396, 440, 398, 438, 400, 448, 1232, 444, 396, 440, 1240, 446, 394, 442,
396, 440, 398, 440, 400, 448, 390, 446, 1232, 444, 1238, 446, 394, 444,
1236, 448, 1232, 442, 396, 440, 398, 448, 1232, 444, 396, 440, 398, 438,
1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, 442, 396, 440, 398, 438,
400, 448, 390, 446, 394, 444, 420, 416, 394, 444, 396, 440, 398, 440, 398,
438, 400, 448, 418, 420, 418, 418, 394, 442, 396, 442, 396, 440, 424, 412,
400, 448, 390, 446, 392, 446, 420, 418, 420, 416, 396, 440, 398, 440, 424,
412, 426, 420, 418, 420, 392, 444, 394, 444, 422, 416, 422, 414, 398, 440,
426, 422, 388, 448, 416, 420, 418, 418, 422, 416, 422, 414, 424, 414, 398,
438, 426, 422, 418, 420, 390, 446, 418, 418, 420, 416, 396, 440, 424, 412,
426, 412, 400, 446, 418, 420, 420, 418, 420, 416, 422, 414, 422, 414, 424,
412, 426, 422, 390, 446, 1232, 442, 1240, 446, 394, 444, 394, 442, 1238,
446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B

irsend.sendRaw(rawData, 583, 33);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type);
EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits);
uint8_t expected[kMitsubishiACStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36,
0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6};
EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits);
}

// Tests for decodeMitsubishiAC() when the repeat mark is wrong.
TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatMarkError) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
// Mitsubishi AC "Power On, 16C, low fan, vane auto move".
uint16_t rawData[583] = {
3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236,
440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394,
444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392,
446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390,
446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446,
392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390,
446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448,
390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438,
402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, 440,
400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 422, 1260, 416,
396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, 422,
1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, 446,
392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, 400,
448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, 448,
390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400,
448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438,
400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, 398,
438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 438,
400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398,
438, 1240, 444, 1264, 422, 390, 446, 392, 446,
// Repeat mark (1111) wrong:
1260, 414, 1268, 418, 1264, 422, 1111, 347, 1708, 418, 1264, 422, 1234,
442, 398, 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234,
442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260,
416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400,
448, 392, 446, 1234, 440, 398, 450, 390, 446, 392, 444, 394, 444, 394,
442, 396, 442, 398, 440, 400, 438, 400, 448, 390, 446, 392, 444, 394, 442,
396, 442, 396, 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394,
442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, 444, 1234,
440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, 448, 1232, 444, 396,
440, 1240, 446, 394, 442, 396, 440, 398, 440, 400, 448, 390, 446, 1232,
444, 1238, 446, 394, 444, 1236, 448, 1232, 442, 396, 440, 398, 448, 1232,
444, 396, 440, 398, 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394,
442, 396, 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, 444,
396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, 418, 394, 442, 396,
442, 396, 440, 424, 412, 400, 448, 390, 446, 392, 446, 420, 418, 420, 416,
396, 440, 398, 440, 424, 412, 426, 420, 418, 420, 392, 444, 394, 444, 422,
416, 422, 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, 416,
422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, 446, 418, 418, 420,
416, 396, 440, 424, 412, 426, 412, 400, 446, 418, 420, 420, 418, 420, 416,
422, 414, 422, 414, 424, 412, 426, 422, 390, 446, 1232, 442, 1240, 446,
394, 444, 394, 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B

irsend.sendRaw(rawData, 583, 33);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type);
EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits);
uint8_t expected[kMitsubishiACStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36,
0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6};
EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits);
}

// Tests for decodeMitsubishiAC() when first payload has an error and the
// repeat mark is wrong.
TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeededButError) {
Expand Down