Skip to content

Commit 575a81b

Browse files
authored
Add support for a 40bit varient of the standard Panasonic protocol (#1977)
This seems to be a shorter version of the normal 48 bit protocol. Different manufacturer code, and slightly different checksum calc. Modified the exist code to support it rather than add a new protocol. Fixes #1976
1 parent fdf35b4 commit 575a81b

File tree

4 files changed

+112
-28
lines changed

4 files changed

+112
-28
lines changed

src/IRrecv.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,12 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
701701
return true;
702702
#endif
703703
#if DECODE_PANASONIC
704-
DPRINTLN("Attempting Panasonic decode");
704+
DPRINTLN("Attempting Panasonic (48-bit) decode");
705705
if (decodePanasonic(results, offset)) return true;
706-
#endif
706+
DPRINTLN("Attempting Panasonic (40-bit) decode");
707+
if (decodePanasonic(results, offset, kPanasonic40Bits, true,
708+
kPanasonic40Manufacturer)) return true;
709+
#endif // DECODE_PANASONIC
707710
#if DECODE_LG
708711
DPRINTLN("Attempting LG (28-bit) decode");
709712
if (decodeLG(results, offset, kLgBits, true)) return true;

src/IRremoteESP8266.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,8 @@ const uint16_t kNeoclimaBits = kNeoclimaStateLength * 8;
13351335
const uint16_t kNeoclimaMinRepeat = kNoRepeat;
13361336
const uint16_t kPanasonicBits = 48;
13371337
const uint32_t kPanasonicManufacturer = 0x4004;
1338+
const uint32_t kPanasonic40Manufacturer = 0x34;
1339+
const uint16_t kPanasonic40Bits = 40;
13381340
const uint16_t kPanasonicAcStateLength = 27;
13391341
const uint16_t kPanasonicAcStateShortLength = 16;
13401342
const uint16_t kPanasonicAcBits = kPanasonicAcStateLength * 8;

src/ir_Panasonic.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,15 @@ uint64_t IRsend::encodePanasonic(const uint16_t manufacturer,
128128
bool IRrecv::decodePanasonic(decode_results *results, uint16_t offset,
129129
const uint16_t nbits, const bool strict,
130130
const uint32_t manufacturer) {
131-
if (strict && nbits != kPanasonicBits)
132-
return false; // Request is out of spec.
131+
if (strict) { // Compliance checks
132+
switch (nbits) {
133+
case kPanasonic40Bits:
134+
case kPanasonicBits:
135+
break;
136+
default:
137+
return false; // Request is out of spec.
138+
}
139+
}
133140

134141
uint64_t data = 0;
135142

@@ -147,8 +154,10 @@ bool IRrecv::decodePanasonic(decode_results *results, uint16_t offset,
147154
if (address != manufacturer) // Verify the Manufacturer code.
148155
return false;
149156
// Verify the checksum.
150-
uint8_t checksumOrig = data;
151-
uint8_t checksumCalc = (data >> 24) ^ (data >> 16) ^ (data >> 8);
157+
const uint8_t checksumOrig = data;
158+
uint8_t checksumCalc = (data >> 16) ^ (data >> 8);
159+
if (nbits != kPanasonic40Bits)
160+
checksumCalc ^= (data >> 24);
152161
if (checksumOrig != checksumCalc) return false;
153162
}
154163

test/ir_Panasonic_test.cpp

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Tests for encodePanasonic().
1414

1515
TEST(TestEncodePanasonic, General) {
16-
IRsendTest irsend(4);
16+
IRsendTest irsend(kGpioUnused);
1717
EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0));
1818
EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1));
1919
EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF));
@@ -28,7 +28,7 @@ TEST(TestEncodePanasonic, General) {
2828

2929
// Test sending typical data only.
3030
TEST(TestSendPanasonic64, SendDataOnly) {
31-
IRsendTest irsend(4);
31+
IRsendTest irsend(kGpioUnused);
3232
irsend.begin();
3333

3434
irsend.reset();
@@ -76,7 +76,7 @@ TEST(TestSendPanasonic64, SendDataOnly) {
7676

7777
// Test sending with different repeats.
7878
TEST(TestSendPanasonic64, SendWithRepeats) {
79-
IRsendTest irsend(4);
79+
IRsendTest irsend(kGpioUnused);
8080
irsend.begin();
8181

8282
irsend.reset();
@@ -147,7 +147,7 @@ TEST(TestSendPanasonic64, SendWithRepeats) {
147147

148148
// Test sending an atypical data size.
149149
TEST(TestSendPanasonic64, SendUnusualSize) {
150-
IRsendTest irsend(4);
150+
IRsendTest irsend(kGpioUnused);
151151
irsend.begin();
152152

153153
irsend.reset();
@@ -213,8 +213,8 @@ TEST(TestSendPanasonic, CompareToSendPanasonic64) {
213213

214214
// Decode normal Panasonic messages.
215215
TEST(TestDecodePanasonic, NormalDecodeWithStrict) {
216-
IRsendTest irsend(4);
217-
IRrecv irrecv(4);
216+
IRsendTest irsend(kGpioUnused);
217+
IRrecv irrecv(kGpioUnused);
218218
irsend.begin();
219219

220220
// Normal Panasonic 48-bit message.
@@ -259,8 +259,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithStrict) {
259259

260260
// Decode normal repeated Panasonic messages.
261261
TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) {
262-
IRsendTest irsend(4);
263-
IRrecv irrecv(4);
262+
IRsendTest irsend(kGpioUnused);
263+
IRrecv irrecv(kGpioUnused);
264264
irsend.begin();
265265

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

294294
// Decode Panasonic messages with unsupported values.
295295
TEST(TestDecodePanasonic, DecodeWithNonStrictValues) {
296-
IRsendTest irsend(4);
297-
IRrecv irrecv(4);
296+
IRsendTest irsend(kGpioUnused);
297+
IRrecv irrecv(kGpioUnused);
298298
irsend.begin();
299299

300300
irsend.reset();
@@ -331,8 +331,8 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictValues) {
331331

332332
// Decode Panasonic messages with unsupported size/lengths.
333333
TEST(TestDecodePanasonic, DecodeWithNonStrictSize) {
334-
IRsendTest irsend(4);
335-
IRrecv irrecv(4);
334+
IRsendTest irsend(kGpioUnused);
335+
IRrecv irrecv(kGpioUnused);
336336
irsend.begin();
337337

338338
irsend.reset();
@@ -375,8 +375,8 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictSize) {
375375

376376
// Decode (non-standard) 64-bit messages.
377377
TEST(TestDecodePanasonic, Decode64BitMessages) {
378-
IRsendTest irsend(4);
379-
IRrecv irrecv(4);
378+
IRsendTest irsend(kGpioUnused);
379+
IRrecv irrecv(kGpioUnused);
380380
irsend.begin();
381381

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

396396
// Decode a 'real' example via GlobalCache
397397
TEST(TestDecodePanasonic, DecodeGlobalCacheExample) {
398-
IRsendTest irsend(4);
399-
IRrecv irrecv(4);
398+
IRsendTest irsend(kGpioUnused);
399+
IRrecv irrecv(kGpioUnused);
400400
irsend.begin();
401401

402402
irsend.reset();
@@ -432,8 +432,8 @@ TEST(TestDecodePanasonic, DecodeGlobalCacheExample) {
432432

433433
// Fail to decode a non-Panasonic example via GlobalCache
434434
TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) {
435-
IRsendTest irsend(4);
436-
IRrecv irrecv(4);
435+
IRsendTest irsend(kGpioUnused);
436+
IRrecv irrecv(kGpioUnused);
437437
irsend.begin();
438438

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

453453
// Failing to decode Panasonic in Issue #245
454454
TEST(TestDecodePanasonic, DecodeIssue245) {
455-
IRsendTest irsend(4);
456-
IRrecv irrecv(4);
455+
IRsendTest irsend(kGpioUnused);
456+
IRrecv irrecv(kGpioUnused);
457457
irsend.begin();
458458

459459
irsend.reset();
@@ -813,8 +813,8 @@ TEST(TestIRPanasonicAcClass, HumanReadable) {
813813

814814
// Decode normal Panasonic AC messages.
815815
TEST(TestDecodePanasonicAC, RealExample) {
816-
IRsendTest irsend(4);
817-
IRrecv irrecv(4);
816+
IRsendTest irsend(kGpioUnused);
817+
IRrecv irrecv(kGpioUnused);
818818
irsend.begin();
819819

820820
// Data from Issue #525
@@ -1586,3 +1586,73 @@ TEST(TestIRPanasonicAc32Class, HumanReadable) {
15861586
"Swing(H): Off, Swing(V): 5 (Lowest)",
15871587
ac.toString());
15881588
}
1589+
1590+
// Decode a 'real' example of a captured 40 bit panasonic message
1591+
TEST(TestDecodePanasonic, RealPanasonic40BitMesg) {
1592+
IRsendTest irsend(kGpioUnused);
1593+
IRrecv irrecv(kGpioUnused);
1594+
irsend.begin();
1595+
1596+
irsend.reset();
1597+
// Panasonic 40 bit code https://github.com/crankyoldgit/IRremoteESP8266/issues/1976#issue-1660147581
1598+
const uint16_t rawData1[83] = {
1599+
3486, 1742,
1600+
432, 456, 406, 456, 406, 1336, 406, 1312, 430, 456, 406, 1334, 408, 456,
1601+
406, 456, 408, 456, 406, 1334, 408, 456, 408, 454, 408, 1334, 408, 456,
1602+
406, 1336, 406, 456, 408, 1334, 408, 456, 406, 456, 408, 1336, 406, 456,
1603+
408, 454, 406, 456, 406, 454, 408, 1332, 410, 1332, 408, 1334, 408, 1336,
1604+
406, 1334, 410, 1332, 410, 454, 406, 456, 406, 456, 406, 1332, 410, 1334,
1605+
408, 454, 406, 1336, 406, 1336, 406, 454, 410, 454, 408}; // UKN 1D41D404
1606+
1607+
irsend.sendRaw(rawData1, 83, 38);
1608+
irsend.makeDecodeResult();
1609+
1610+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
1611+
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
1612+
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
1613+
EXPECT_EQ(0x344A90FC6C, irsend.capture.value);
1614+
EXPECT_EQ(0x34, irsend.capture.address);
1615+
EXPECT_EQ(0x4A90FC6C, irsend.capture.command);
1616+
EXPECT_FALSE(irsend.capture.repeat);
1617+
1618+
// night ch3 from https://github.com/crankyoldgit/IRremoteESP8266/issues/1976#issuecomment-1501736104
1619+
const uint16_t rawData2[83] = {
1620+
3490, 1734,
1621+
440, 426, 460, 400, 438, 1304, 438, 1302, 440, 426, 436, 1302, 464, 400,
1622+
462, 400, 462, 402, 462, 1278, 438, 426, 438, 426, 460, 1282, 434, 428,
1623+
434, 1308, 460, 402, 460, 1280, 440, 422, 438, 426, 436, 1306, 438, 424,
1624+
462, 402, 436, 426, 462, 400, 438, 426, 436, 1304, 434, 1308, 438, 1304,
1625+
464, 1278, 436, 1306, 466, 398, 464, 398, 466, 1276, 466, 1274, 464, 1280,
1626+
462, 402, 436, 1304, 466, 1276, 440, 422, 440, 424, 460}; // UKN DAE32FFC
1627+
irsend.reset();
1628+
1629+
irsend.sendRaw(rawData2, 83, 38);
1630+
irsend.makeDecodeResult();
1631+
1632+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
1633+
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
1634+
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
1635+
EXPECT_EQ(0x344A907CEC, irsend.capture.value);
1636+
EXPECT_EQ(0x34, irsend.capture.address);
1637+
EXPECT_EQ(0x4A907CEC, irsend.capture.command);
1638+
EXPECT_FALSE(irsend.capture.repeat);
1639+
}
1640+
1641+
// recreate the above real message, synthetically.
1642+
TEST(TestDecodePanasonic, SynthticPanasonic40BitMesg) {
1643+
IRsendTest irsend(kGpioUnused);
1644+
IRrecv irrecv(kGpioUnused);
1645+
irsend.begin();
1646+
irsend.reset();
1647+
1648+
irsend.sendPanasonic64(0x344A90FC6C, kPanasonic40Bits);
1649+
irsend.makeDecodeResult();
1650+
1651+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
1652+
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
1653+
EXPECT_EQ(kPanasonic40Bits, irsend.capture.bits);
1654+
EXPECT_EQ(0x344A90FC6C, irsend.capture.value);
1655+
EXPECT_EQ(0x34, irsend.capture.address);
1656+
EXPECT_EQ(0x4A90FC6C, irsend.capture.command);
1657+
EXPECT_FALSE(irsend.capture.repeat);
1658+
}

0 commit comments

Comments
 (0)