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
7 changes: 5 additions & 2 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,9 +701,12 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
return true;
#endif
#if DECODE_PANASONIC
DPRINTLN("Attempting Panasonic decode");
DPRINTLN("Attempting Panasonic (48-bit) decode");
if (decodePanasonic(results, offset)) return true;
#endif
DPRINTLN("Attempting Panasonic (40-bit) decode");
if (decodePanasonic(results, offset, kPanasonic40Bits, true,
kPanasonic40Manufacturer)) return true;
#endif // DECODE_PANASONIC
#if DECODE_LG
DPRINTLN("Attempting LG (28-bit) decode");
if (decodeLG(results, offset, kLgBits, true)) return true;
Expand Down
2 changes: 2 additions & 0 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,8 @@ const uint16_t kNeoclimaBits = kNeoclimaStateLength * 8;
const uint16_t kNeoclimaMinRepeat = kNoRepeat;
const uint16_t kPanasonicBits = 48;
const uint32_t kPanasonicManufacturer = 0x4004;
const uint32_t kPanasonic40Manufacturer = 0x34;
const uint16_t kPanasonic40Bits = 40;
const uint16_t kPanasonicAcStateLength = 27;
const uint16_t kPanasonicAcStateShortLength = 16;
const uint16_t kPanasonicAcBits = kPanasonicAcStateLength * 8;
Expand Down
17 changes: 13 additions & 4 deletions src/ir_Panasonic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,15 @@ uint64_t IRsend::encodePanasonic(const uint16_t manufacturer,
bool IRrecv::decodePanasonic(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict,
const uint32_t manufacturer) {
if (strict && nbits != kPanasonicBits)
return false; // Request is out of spec.
if (strict) { // Compliance checks
switch (nbits) {
case kPanasonic40Bits:
case kPanasonicBits:
break;
default:
return false; // Request is out of spec.
}
}

uint64_t data = 0;

Expand All @@ -147,8 +154,10 @@ bool IRrecv::decodePanasonic(decode_results *results, uint16_t offset,
if (address != manufacturer) // Verify the Manufacturer code.
return false;
// Verify the checksum.
uint8_t checksumOrig = data;
uint8_t checksumCalc = (data >> 24) ^ (data >> 16) ^ (data >> 8);
const uint8_t checksumOrig = data;
uint8_t checksumCalc = (data >> 16) ^ (data >> 8);
if (nbits != kPanasonic40Bits)
checksumCalc ^= (data >> 24);
if (checksumOrig != checksumCalc) return false;
}

Expand Down
114 changes: 92 additions & 22 deletions test/ir_Panasonic_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// Tests for encodePanasonic().

TEST(TestEncodePanasonic, General) {
IRsendTest irsend(4);
IRsendTest irsend(kGpioUnused);
EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0));
EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1));
EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF));
Expand All @@ -28,7 +28,7 @@ TEST(TestEncodePanasonic, General) {

// Test sending typical data only.
TEST(TestSendPanasonic64, SendDataOnly) {
IRsendTest irsend(4);
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -76,7 +76,7 @@ TEST(TestSendPanasonic64, SendDataOnly) {

// Test sending with different repeats.
TEST(TestSendPanasonic64, SendWithRepeats) {
IRsendTest irsend(4);
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -147,7 +147,7 @@ TEST(TestSendPanasonic64, SendWithRepeats) {

// Test sending an atypical data size.
TEST(TestSendPanasonic64, SendUnusualSize) {
IRsendTest irsend(4);
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -213,8 +213,8 @@ TEST(TestSendPanasonic, CompareToSendPanasonic64) {

// Decode normal Panasonic messages.
TEST(TestDecodePanasonic, NormalDecodeWithStrict) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Normal Panasonic 48-bit message.
Expand Down Expand Up @@ -259,8 +259,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithStrict) {

// Decode normal repeated Panasonic messages.
TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Normal Panasonic 48-bit message with 2 repeats.
Expand Down Expand Up @@ -293,8 +293,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) {

// Decode Panasonic messages with unsupported values.
TEST(TestDecodePanasonic, DecodeWithNonStrictValues) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -331,8 +331,8 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictValues) {

// Decode Panasonic messages with unsupported size/lengths.
TEST(TestDecodePanasonic, DecodeWithNonStrictSize) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -375,8 +375,8 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictSize) {

// Decode (non-standard) 64-bit messages.
TEST(TestDecodePanasonic, Decode64BitMessages) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand All @@ -395,8 +395,8 @@ TEST(TestDecodePanasonic, Decode64BitMessages) {

// Decode a 'real' example via GlobalCache
TEST(TestDecodePanasonic, DecodeGlobalCacheExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -432,8 +432,8 @@ TEST(TestDecodePanasonic, DecodeGlobalCacheExample) {

// Fail to decode a non-Panasonic example via GlobalCache
TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand All @@ -452,8 +452,8 @@ TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) {

// Failing to decode Panasonic in Issue #245
TEST(TestDecodePanasonic, DecodeIssue245) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
Expand Down Expand Up @@ -813,8 +813,8 @@ TEST(TestIRPanasonicAcClass, HumanReadable) {

// Decode normal Panasonic AC messages.
TEST(TestDecodePanasonicAC, RealExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Data from Issue #525
Expand Down Expand Up @@ -1586,3 +1586,73 @@ TEST(TestIRPanasonicAc32Class, HumanReadable) {
"Swing(H): Off, Swing(V): 5 (Lowest)",
ac.toString());
}

// Decode a 'real' example of a captured 40 bit panasonic message
TEST(TestDecodePanasonic, RealPanasonic40BitMesg) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

irsend.reset();
// Panasonic 40 bit code https://github.com/crankyoldgit/IRremoteESP8266/issues/1976#issue-1660147581
const uint16_t rawData1[83] = {
3486, 1742,
432, 456, 406, 456, 406, 1336, 406, 1312, 430, 456, 406, 1334, 408, 456,
406, 456, 408, 456, 406, 1334, 408, 456, 408, 454, 408, 1334, 408, 456,
406, 1336, 406, 456, 408, 1334, 408, 456, 406, 456, 408, 1336, 406, 456,
408, 454, 406, 456, 406, 454, 408, 1332, 410, 1332, 408, 1334, 408, 1336,
406, 1334, 410, 1332, 410, 454, 406, 456, 406, 456, 406, 1332, 410, 1334,
408, 454, 406, 1336, 406, 1336, 406, 454, 410, 454, 408}; // UKN 1D41D404

irsend.sendRaw(rawData1, 83, 38);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
EXPECT_EQ(0x344A90FC6C, irsend.capture.value);
EXPECT_EQ(0x34, irsend.capture.address);
EXPECT_EQ(0x4A90FC6C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);

// night ch3 from https://github.com/crankyoldgit/IRremoteESP8266/issues/1976#issuecomment-1501736104
const uint16_t rawData2[83] = {
3490, 1734,
440, 426, 460, 400, 438, 1304, 438, 1302, 440, 426, 436, 1302, 464, 400,
462, 400, 462, 402, 462, 1278, 438, 426, 438, 426, 460, 1282, 434, 428,
434, 1308, 460, 402, 460, 1280, 440, 422, 438, 426, 436, 1306, 438, 424,
462, 402, 436, 426, 462, 400, 438, 426, 436, 1304, 434, 1308, 438, 1304,
464, 1278, 436, 1306, 466, 398, 464, 398, 466, 1276, 466, 1274, 464, 1280,
462, 402, 436, 1304, 466, 1276, 440, 422, 440, 424, 460}; // UKN DAE32FFC
irsend.reset();

irsend.sendRaw(rawData2, 83, 38);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
EXPECT_EQ(0x344A907CEC, irsend.capture.value);
EXPECT_EQ(0x34, irsend.capture.address);
EXPECT_EQ(0x4A907CEC, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}

// recreate the above real message, synthetically.
TEST(TestDecodePanasonic, SynthticPanasonic40BitMesg) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();

irsend.sendPanasonic64(0x344A90FC6C, kPanasonic40Bits);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
EXPECT_EQ(0x344A90FC6C, irsend.capture.value);
EXPECT_EQ(0x34, irsend.capture.address);
EXPECT_EQ(0x4A90FC6C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}