From 4f233ff0a31f30ac03328040d756b79ccfe53ab0 Mon Sep 17 00:00:00 2001 From: Albert Kharisov Date: Wed, 15 Sep 2021 20:22:58 +0300 Subject: [PATCH] [FL-1800] IRDA: enc/decoder refactoring, Add NEC42 (#705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP: IRDA: multilen protocol refactoring, NEC42 * IRDA: Refactoring encoder/decoder Co-authored-by: あく --- .../irda_decoder_encoder_test.c | 17 +- .../test_data/irda_nec_test_data.srcdata | 96 +++++++ .../test_data/irda_necext_test_data.srcdata | 270 +++++++++--------- .../test_data/irda_sirc_test_data.srcdata | 14 +- .../common/irda_common_decoder.c | 248 ++++++++-------- .../common/irda_common_encoder.c | 75 ++--- .../encoder_decoder/common/irda_common_i.h | 16 +- .../common/irda_common_protocol_defs.c | 21 +- lib/irda/encoder_decoder/irda.c | 1 + lib/irda/encoder_decoder/irda.h | 18 +- lib/irda/encoder_decoder/irda_i.h | 1 + .../encoder_decoder/irda_protocol_defs_i.h | 10 +- .../encoder_decoder/nec/irda_decoder_nec.c | 48 +++- .../encoder_decoder/nec/irda_encoder_nec.c | 41 ++- lib/irda/encoder_decoder/nec/irda_nec_spec.c | 20 ++ .../encoder_decoder/rc5/irda_encoder_rc5.c | 1 + .../encoder_decoder/rc6/irda_decoder_rc6.c | 14 +- .../encoder_decoder/rc6/irda_encoder_rc6.c | 1 + .../samsung/irda_encoder_samsung.c | 4 +- .../encoder_decoder/sirc/irda_decoder_sirc.c | 36 +-- .../encoder_decoder/sirc/irda_encoder_sirc.c | 36 +-- 21 files changed, 551 insertions(+), 437 deletions(-) diff --git a/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c b/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c index 55403b95..01bca32d 100644 --- a/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c +++ b/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c @@ -129,10 +129,7 @@ static void run_encoder_decoder(const IrdaMessage input_messages[], uint32_t inp for(int i = 0; i < timings_len; ++i) { message_decoded = irda_decode(decoder_handler, level, timings[i]); if((i == timings_len - 2) && level && message_decoded) { - /* In case we end with space timing - message can be decoded at last mark. - * Exception - SIRC protocol, which has variable message length (12/15/20), - * and decoder recognizes protocol by silence time before next message - * or by timeout (irda_check_decoder_ready()). */ + /* In case we end with space timing - message can be decoded at last mark */ break; } else if(i < timings_len - 1) { mu_check(!message_decoded); @@ -225,17 +222,16 @@ MU_TEST(test_mix) { RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); RUN_DECODER(test_decoder_sirc_input5, test_decoder_sirc_expected5); + RUN_DECODER(test_decoder_nec_input3, test_decoder_nec_expected3); RUN_DECODER(test_decoder_rc5_input5, test_decoder_rc5_expected5); RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); RUN_DECODER(test_decoder_sirc_input3, test_decoder_sirc_expected3); } -MU_TEST(test_decoder_nec1) { +MU_TEST(test_decoder_nec) { RUN_DECODER(test_decoder_nec_input1, test_decoder_nec_expected1); -} - -MU_TEST(test_decoder_nec2) { RUN_DECODER(test_decoder_nec_input2, test_decoder_nec_expected2); + RUN_DECODER(test_decoder_nec_input3, test_decoder_nec_expected3); } MU_TEST(test_decoder_unexpected_end_in_sequence) { @@ -295,6 +291,8 @@ MU_TEST(test_encoder_rc6) { MU_TEST(test_encoder_decoder_all) { RUN_ENCODER_DECODER(test_nec); RUN_ENCODER_DECODER(test_necext); + RUN_ENCODER_DECODER(test_nec42); + RUN_ENCODER_DECODER(test_nec42ext); RUN_ENCODER_DECODER(test_samsung32); RUN_ENCODER_DECODER(test_rc6); RUN_ENCODER_DECODER(test_rc5); @@ -312,8 +310,7 @@ MU_TEST_SUITE(test_irda_decoder_encoder) { MU_RUN_TEST(test_decoder_rc6); MU_RUN_TEST(test_encoder_rc6); MU_RUN_TEST(test_decoder_unexpected_end_in_sequence); - MU_RUN_TEST(test_decoder_nec1); - MU_RUN_TEST(test_decoder_nec2); + MU_RUN_TEST(test_decoder_nec); MU_RUN_TEST(test_decoder_samsung32); MU_RUN_TEST(test_decoder_necext1); MU_RUN_TEST(test_mix); diff --git a/applications/tests/irda_decoder_encoder/test_data/irda_nec_test_data.srcdata b/applications/tests/irda_decoder_encoder/test_data/irda_nec_test_data.srcdata index 9b4dae7e..f97f31ca 100644 --- a/applications/tests/irda_decoder_encoder/test_data/irda_nec_test_data.srcdata +++ b/applications/tests/irda_decoder_encoder/test_data/irda_nec_test_data.srcdata @@ -178,6 +178,45 @@ const IrdaMessage test_decoder_nec_expected2[] = { {IrdaProtocolNEC, 0x00, 0x0A, true}, }; +const uint32_t test_decoder_nec_input3[] = { +200000, 8862, 4452, 562, 563, 559, 1681, 563, 1646, 567, 586, 556, 569, 563, 583, 559, 571, 561, 1675, 559, 565, 567, 1673, 561, 561, 561, 592, 561, 565, 567, 579, 563, 567, 565, 584, 558, 1652, 561, 592, 561, 561, 561, 1679, 565, 560, 562, 584, 558, 1659, 564, 585, 557, 566, 566, 1675, 559, 1649, 564, 589, 564, 1649, 564, 1668, 566, 565, 567, 1669, 565, + 43470, 8896, 4432, 561, 561, 561, 1679, 565, 1648, 565, 581, 561, 568, 564, 586, 567, 558, 564, 1676, 558, 564, 558, 1681, 563, 563, 559, 587, 566, 565, 567, 582, 561, 564, 558, 595, 558, 1650, 563, 590, 563, 563, 559, 1674, 560, 570, 562, 587, 566, 1645, 568, 586, 556, 565, 567, 1672, 562, 1651, 562, 584, 558, 1658, 566, 1671, 563, 561, 561, 1679, 565, +200000, 8881, 4383, 569, 549, 573, 548, 574, 541, 571, 550, 572, 547, 575, 539, 573, 551, 571, 1651, 573, 545, 567, 554, 568, 548, 574, 1652, 572, 547, 575, 1645, 568, 1661, 573, 545, 567, 1657, 567, 554, 568, 547, 575, 1652, 572, 547, 575, 539, 573, 1657, 567, 550, 572, 545, 577, 1651, 573, 1648, 576, 545, 567, 1659, 575, 1645, 568, 555, 567, 1657, 567, + 38995, 8883, 4369, 573, 543, 569, 552, 570, 549, 573, 541, 571, 553, 569, 548, 574, 543, 569, 1658, 566, 550, 572, 548, 574, 546, 566, 1653, 571, 553, 569, 1654, 570, 1654, 570, 551, 571, 1651, 573, 547, 575, 545, 567, 1653, 571, 552, 570, 547, 575, 1649, 564, 556, 566, 550, 572, 1655, 569, 1656, 568, 546, 566, 1664, 570, 1653, 571, 547, 565, 1663, 571, +200000, 8987, 4504, 561, 593, 539, 589, 533, 596, 515, 586, 536, 592, 540, 588, 534, 595, 517, 1713, 541, 1664, 570, 1686, 558, 596, 515, 587, 535, 593, 539, 1691, 543, 1689, 565, 588, 513, 1691, 563, 1668, 617, 1613, 641, 1615, 567, 587, 535, 593, 519, 610, 512, 590, 542, 1714, 510, 593, 539, 1691, 563, 591, 510, 1720, 535, 594, 518, 584, 538, 591, 541, + 39546, 8990, 4501, 565, 590, 542, 586, 536, 593, 508, 593, 539, 589, 543, 585, 537, 592, 509, 1720, 545, 1660, 615, 1642, 561, 567, 534, 594, 538, 590, 542, 1688, 535, 1696, 558, 595, 517, 1687, 567, 1664, 621, 1635, 619, 1611, 561, 594, 538, 590, 511, 617, 515, 586, 536, 1721, 513, 589, 543, 1687, 568, 587, 514, 1691, 563, 590, 511, 591, 541, 587, 535, +200000, 8986, 4505, 560, 594, 538, 590, 542, 586, 515, 586, 536, 593, 539, 589, 533, 595, 517, 1714, 540, 587, 535, 594, 518, 1713, 542, 586, 515, 587, 535, 1722, 543, 1662, 562, 592, 540, 1664, 570, 585, 537, 591, 541, 1689, 545, 584, 538, 590, 542, 1688, 536, 593, 539, 589, 512, 590, 542, 586, 536, 1720, 514, 588, 544, 585, 537, 591, 541, 587, 514, + 40671, 8986, 4505, 560, 594, 538, 590, 542, 586, 515, 587, 535, 593, 539, 589, 533, 595, 516, 1714, 541, 587, 535, 594, 518, 1712, 542, 586, 515, 587, 535, 1722, 543, 1662, 561, 592, 540, 1664, 570, 585, 537, 591, 541, 1689, 545, 584, 538, 590, 542, 1688, 536, 593, 539, 589, 512, 590, 542, 586, 536, 1720, 514, 588, 544, 585, 537, 591, 541, 587, 514, +200000, 8990, 4500, 566, 1692, 562, 1668, 566, 588, 534, 594, 518, 584, 538, 591, 541, 587, 535, 1669, 565, 589, 543, 1688, 536, 592, 540, 1691, 563, 1667, 567, 1664, 621, 1635, 568, 586, 515, 587, 535, 593, 539, 589, 543, 1662, 562, 592, 540, 588, 534, 594, 518, 585, 537, 591, 541, 587, 514, 587, 535, 594, 538, 590, 542, 586, 515, 586, 536, 593, 539, + 39544, 8993, 4498, 567, 1690, 564, 1666, 568, 586, 536, 593, 508, 593, 539, 589, 543, 585, 537, 1668, 566, 588, 544, 1687, 537, 591, 541, 1690, 564, 1666, 568, 1663, 561, 1696, 569, 585, 516, 586, 536, 593, 539, 589, 543, 1661, 562, 592, 540, 588, 534, 594, 517, 584, 538, 591, 541, 587, 514, 587, 535, 593, 539, 589, 543, 585, 516, 586, 536, 592, 540, +200000, 8894, 4456, 589, 1676, 589, 571, 582, 574, 589, 571, 582, 1683, 582, 1677, 588, 1682, 583, 574, 589, 568, 585, 1682, 583, 1678, 587, 1680, 585, 574, 589, 565, 588, 575, 588, 1675, 590, 567, 586, 1681, 584, 571, 582, 1685, 590, 568, 585, 569, 584, 1685, 590, 567, 586, 1678, 587, 574, 589, 1672, 582, 578, 585, 1679, 586, 1674, 591, 572, 591, 1672, 582, + 39632, 8912, 4464, 560, 1703, 562, 598, 565, 594, 559, 594, 559, 1711, 564, 1698, 567, 1697, 568, 593, 560, 595, 568, 1698, 567, 1698, 567, 1693, 561, 602, 561, 596, 567, 590, 563, 1704, 561, 594, 559, 1707, 568, 591, 562, 1697, 568, 596, 567, 590, 563, 1700, 565, 596, 567, 1693, 561, 599, 564, 1701, 564, 589, 564, 1706, 559, 1704, 561, 597, 566, 1700, 565, +200000, 9018, 4500, 565, 1666, 568, 1689, 565, 588, 513, 1691, 615, 1616, 618, 1639, 564, 1667, 567, 587, 535, 594, 538, 563, 538, 590, 542, 586, 536, 593, 508, 593, 539, 589, 543, 1688, 535, 592, 540, 588, 544, 585, 537, 591, 510, 1694, 560, 1670, 564, 1693, 562, 1669, 565, 1692, 542, 1689, 565, 588, 534, 595, 517, 585, 537, 591, 541, 587, 535, 568, 544, 584, 538, 591, 541, 1663, 560, 1696, 569, 1662, 562, 1695, 539, 1692, 614, 1616, 566, 1691, 563, 1667, 567, + 23184, 9012, 4505, 560, 1697, 537, 1693, 561, 593, 508, 1696, 569, 1662, 562, 1695, 560, 1671, 563, 591, 541, 587, 535, 594, 518, 584, 538, 590, 542, 586, 515, 613, 509, 593, 539, 1692, 542, 585, 537, 592, 540, 588, 534, 594, 518, 1687, 567, 1663, 560, 1697, 568, 1662, 562, 1695, 539, 1692, 563, 591, 541, 587, 514, 588, 544, 584, 538, 590, 542, 586, 515, 587, 535, 593, 539, 1666, 568, 1689, 565, 1665, 569, 1688, 536, 1695, 570, 1661, 562, 1694, 561, 1670, 564, +200000, 8835, 4446, 537, 562, 539, 562, 539, 1663, 540, 1667, 536, 1669, 534, 560, 531, 573, 539, 559, 532, 1672, 531, 570, 531, 564, 537, 563, 538, 561, 540, 1660, 533, 1677, 536, 561, 540, 557, 534, 567, 534, 1668, 535, 1672, 531, 1675, 538, 555, 536, 1674, 539, 1665, 538, 1666, 537, 1671, 532, 563, 538, 1669, 534, 566, 535, 558, 533, 1677, 536, 562, 539, 558, 533, 568, 533, 1668, 535, 566, 535, 1670, 533, 1667, 536, 568, 533, 1671, 532, 1672, 531, 1676, 537, + 22779, 8870, 4437, 535, + 92592, 8861, 4414, 538, +}; + +const IrdaMessage test_decoder_nec_expected3[] = { + {IrdaProtocolNECext, 0x286, 0xB649, false}, + {IrdaProtocolNECext, 0x286, 0xB649, false}, + {IrdaProtocolNECext, 0x6880, 0xB649, false}, + {IrdaProtocolNECext, 0x6880, 0xB649, false}, + {IrdaProtocolNECext, 0x6380, 0x150F, false}, + {IrdaProtocolNECext, 0x6380, 0x150F, false}, + {IrdaProtocolNECext, 0x6480, 0x849, false}, + {IrdaProtocolNECext, 0x6480, 0x849, false}, + {IrdaProtocolNECext, 0x7A83, 0x8, false}, + {IrdaProtocolNECext, 0x7A83, 0x8, false}, + {IrdaProtocolNEC, 0x71, 0x4A, false}, + {IrdaProtocolNEC, 0x71, 0x4A, false}, + {IrdaProtocolNEC42, 0x7B, 0x0, false}, + {IrdaProtocolNEC42, 0x7B, 0x0, false}, + {IrdaProtocolNEC42, 0x11C, 0x12, false}, +}; + + const IrdaMessage test_nec[] = { {IrdaProtocolNEC, 0x00, 0x00, false}, {IrdaProtocolNEC, 0x01, 0x00, false}, @@ -209,4 +248,61 @@ const IrdaMessage test_nec[] = { {IrdaProtocolNEC, 0x55, 0x55, true}, }; +const IrdaMessage test_nec42[] = { + {IrdaProtocolNEC42, 0x0000, 0x00, false}, + {IrdaProtocolNEC42, 0x0001, 0x00, false}, + {IrdaProtocolNEC42, 0x0001, 0x80, false}, + {IrdaProtocolNEC42, 0x0000, 0x80, false}, + {IrdaProtocolNEC42, 0x0000, 0x00, false}, + {IrdaProtocolNEC42, 0x0000, 0x00, true}, + {IrdaProtocolNEC42, 0x0000, 0x00, false}, + {IrdaProtocolNEC42, 0x0000, 0x00, true}, + {IrdaProtocolNEC42, 0x1FFF, 0xFF, false}, + {IrdaProtocolNEC42, 0x1FFE, 0xFF, false}, + {IrdaProtocolNEC42, 0x1FFE, 0x7F, false}, + {IrdaProtocolNEC42, 0x1FFF, 0x7F, false}, + {IrdaProtocolNEC42, 0x1FFF, 0xFF, false}, + {IrdaProtocolNEC42, 0x1FFF, 0xFF, true}, + {IrdaProtocolNEC42, 0x0AAA, 0x55, false}, + {IrdaProtocolNEC42, 0x1555, 0xAA, false}, + {IrdaProtocolNEC42, 0x1555, 0x55, false}, + {IrdaProtocolNEC42, 0x0AAA, 0xAA, false}, + {IrdaProtocolNEC42, 0x0AAA, 0xAA, true}, + {IrdaProtocolNEC42, 0x0AAA, 0xAA, false}, + {IrdaProtocolNEC42, 0x0AAA, 0xAA, true}, + {IrdaProtocolNEC42, 0x0AAA, 0xAA, true}, + {IrdaProtocolNEC42, 0x1555, 0x55, false}, + {IrdaProtocolNEC42, 0x1555, 0x55, true}, + {IrdaProtocolNEC42, 0x1555, 0x55, true}, + {IrdaProtocolNEC42, 0x1555, 0x55, true}, +}; + +const IrdaMessage test_nec42ext[] = { + {IrdaProtocolNEC42ext, 0x0000000, 0x0000, false}, + {IrdaProtocolNEC42ext, 0x0000001, 0x0000, false}, + {IrdaProtocolNEC42ext, 0x0000001, 0x8000, false}, + {IrdaProtocolNEC42ext, 0x0000000, 0x8000, false}, + {IrdaProtocolNEC42ext, 0x0000000, 0x0000, false}, + {IrdaProtocolNEC42ext, 0x0000000, 0x0000, true}, + {IrdaProtocolNEC42ext, 0x0000000, 0x0000, false}, + {IrdaProtocolNEC42ext, 0x0000000, 0x0000, true}, + {IrdaProtocolNEC42ext, 0x3F000FF, 0xF00F, false}, + {IrdaProtocolNEC42ext, 0x3F000FE, 0xF00F, false}, + {IrdaProtocolNEC42ext, 0x3F000FE, 0x700F, false}, + {IrdaProtocolNEC42ext, 0x3F000FF, 0x700F, false}, + {IrdaProtocolNEC42ext, 0x3F000FF, 0xF00F, false}, + {IrdaProtocolNEC42ext, 0x3F000FF, 0xF00F, true}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0x5555, false}, + {IrdaProtocolNEC42ext, 0x1555555, 0xAAAA, false}, + {IrdaProtocolNEC42ext, 0x1555555, 0x5555, false}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0xAAAA, false}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0xAAAA, true}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0xAAAA, false}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0xAAAA, true}, + {IrdaProtocolNEC42ext, 0x2AAAAAA, 0xAAAA, true}, + {IrdaProtocolNEC42ext, 0x1555555, 0x5555, false}, + {IrdaProtocolNEC42ext, 0x1555555, 0x5555, true}, + {IrdaProtocolNEC42ext, 0x1555555, 0x5555, true}, + {IrdaProtocolNEC42ext, 0x1555555, 0x5555, true}, +}; diff --git a/applications/tests/irda_decoder_encoder/test_data/irda_necext_test_data.srcdata b/applications/tests/irda_decoder_encoder/test_data/irda_necext_test_data.srcdata index 66c4f947..edd60768 100644 --- a/applications/tests/irda_decoder_encoder/test_data/irda_necext_test_data.srcdata +++ b/applications/tests/irda_decoder_encoder/test_data/irda_necext_test_data.srcdata @@ -111,147 +111,145 @@ const uint32_t test_decoder_necext_input1[] = { }; const IrdaMessage test_decoder_necext_expected1[] = { - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, false}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, - {IrdaProtocolNECext, 0x7984, 0x12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, false}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, + {IrdaProtocolNECext, 0x7984, 0xed12, true}, }; - - const IrdaMessage test_necext[] = { - {IrdaProtocolNECext, 0x0000, 0x00, false}, - {IrdaProtocolNECext, 0x0001, 0x00, false}, - {IrdaProtocolNECext, 0x0001, 0x80, false}, - {IrdaProtocolNECext, 0x0000, 0x80, false}, - {IrdaProtocolNECext, 0x0000, 0x00, false}, - {IrdaProtocolNECext, 0x0000, 0x00, true}, - {IrdaProtocolNECext, 0x0000, 0x00, false}, - {IrdaProtocolNECext, 0x0000, 0x00, true}, - {IrdaProtocolNECext, 0xFFFF, 0xFF, false}, - {IrdaProtocolNECext, 0xFFFE, 0xFF, false}, - {IrdaProtocolNECext, 0xFFFE, 0x7F, false}, - {IrdaProtocolNECext, 0xFFFF, 0x7F, false}, - {IrdaProtocolNECext, 0xFFFF, 0xFF, false}, - {IrdaProtocolNECext, 0xFFFF, 0xFF, true}, - {IrdaProtocolNECext, 0xAAAA, 0x55, false}, - {IrdaProtocolNECext, 0x5555, 0xAA, false}, - {IrdaProtocolNECext, 0x5555, 0x55, false}, - {IrdaProtocolNECext, 0xAAAA, 0xAA, false}, - {IrdaProtocolNECext, 0xAAAA, 0xAA, true}, + {IrdaProtocolNECext, 0x0000, 0x0000, false}, + {IrdaProtocolNECext, 0x0001, 0x0000, false}, + {IrdaProtocolNECext, 0x0001, 0x8000, false}, + {IrdaProtocolNECext, 0x0000, 0x8000, false}, + {IrdaProtocolNECext, 0x0000, 0x0000, false}, + {IrdaProtocolNECext, 0x0000, 0x0000, true}, + {IrdaProtocolNECext, 0x0000, 0x0000, false}, + {IrdaProtocolNECext, 0x0000, 0x0000, true}, + {IrdaProtocolNECext, 0xFFFF, 0xFFFF, false}, + {IrdaProtocolNECext, 0xFFFE, 0xFFFF, false}, + {IrdaProtocolNECext, 0xFFFE, 0x7FFF, false}, + {IrdaProtocolNECext, 0xFFFF, 0x7FFF, false}, + {IrdaProtocolNECext, 0xFFFF, 0xFFFF, false}, + {IrdaProtocolNECext, 0xFFFF, 0xFFFF, true}, + {IrdaProtocolNECext, 0xAAAA, 0x5555, false}, + {IrdaProtocolNECext, 0x5555, 0xAAAA, false}, + {IrdaProtocolNECext, 0x5555, 0x5555, false}, + {IrdaProtocolNECext, 0xAAAA, 0xAAAA, false}, + {IrdaProtocolNECext, 0xAAAA, 0xAAAA, true}, - {IrdaProtocolNECext, 0xAAAA, 0xAA, false}, - {IrdaProtocolNECext, 0xAAAA, 0xAA, true}, - {IrdaProtocolNECext, 0xAAAA, 0xAA, true}, + {IrdaProtocolNECext, 0xAAAA, 0xAAAA, false}, + {IrdaProtocolNECext, 0xAAAA, 0xAAAA, true}, + {IrdaProtocolNECext, 0xAAAA, 0xAAAA, true}, - {IrdaProtocolNECext, 0x5555, 0x55, false}, - {IrdaProtocolNECext, 0x5555, 0x55, true}, - {IrdaProtocolNECext, 0x5555, 0x55, true}, - {IrdaProtocolNECext, 0x5555, 0x55, true}, + {IrdaProtocolNECext, 0x5555, 0x5555, false}, + {IrdaProtocolNECext, 0x5555, 0x5555, true}, + {IrdaProtocolNECext, 0x5555, 0x5555, true}, + {IrdaProtocolNECext, 0x5555, 0x5555, true}, }; diff --git a/applications/tests/irda_decoder_encoder/test_data/irda_sirc_test_data.srcdata b/applications/tests/irda_decoder_encoder/test_data/irda_sirc_test_data.srcdata index 2968aaca..bacf4be5 100644 --- a/applications/tests/irda_decoder_encoder/test_data/irda_sirc_test_data.srcdata +++ b/applications/tests/irda_decoder_encoder/test_data/irda_sirc_test_data.srcdata @@ -426,20 +426,14 @@ const IrdaMessage test_decoder_sirc_expected5[] = { {IrdaProtocolSIRC20, 0xFB5, 0x53, false}, }; - - - const IrdaMessage test_encoder_sirc_input1[] = { {IrdaProtocolSIRC, 0xA, 0x55, false}, }; const uint32_t test_encoder_sirc_expected1[] = { -10000, 2400, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, +10000, 2400, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 600, }; - - - const IrdaMessage test_encoder_sirc_input2[] = { {IrdaProtocolSIRC15, 0x7D, 0x53, false}, {IrdaProtocolSIRC15, 0x7D, 0x53, true}, @@ -447,9 +441,9 @@ const IrdaMessage test_encoder_sirc_input2[] = { }; const uint32_t test_encoder_sirc_expected2[] = { - 10000, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, /* 2 low levels in row */ - 18000, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, /* 2 low levels in row */ - 18000, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, 600, + 10000, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, + 18600, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, + 18600, 2400, 600, 1200, 600, 1200, 600, 600, 600, 600, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 600, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 1200, 600, 600, }; const IrdaMessage test_sirc[] = { diff --git a/lib/irda/encoder_decoder/common/irda_common_decoder.c b/lib/irda/encoder_decoder/common/irda_common_decoder.c index d64b798d..87458f37 100644 --- a/lib/irda/encoder_decoder/common/irda_common_decoder.c +++ b/lib/irda/encoder_decoder/common/irda_common_decoder.c @@ -1,4 +1,5 @@ #include "furi/check.h" +#include "furi/common_defines.h" #include "irda.h" #include "irda_common_i.h" #include @@ -39,11 +40,12 @@ static bool irda_check_preamble(IrdaCommonDecoder* decoder) { bool result = false; bool start_level = (decoder->level + decoder->timings_cnt + 1) % 2; + if (decoder->timings_cnt == 0) + return false; + // align to start at Mark timing if (!start_level) { - if (decoder->timings_cnt > 0) { - decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); - } + decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); } if (decoder->protocol->timings.preamble_mark == 0) { @@ -66,45 +68,75 @@ static bool irda_check_preamble(IrdaCommonDecoder* decoder) { return result; } -/* Pulse Distance Modulation */ -IrdaStatus irda_common_decode_pdm(IrdaCommonDecoder* decoder) { + +/** + * decoder->protocol->databit_len[0] contains biggest amount of bits, for this protocol. + * decoder->protocol->databit_len[1...] contains lesser values, but which can be decoded + * for some protocol modifications. + */ +static IrdaStatus irda_common_decode_bits(IrdaCommonDecoder* decoder) { furi_assert(decoder); - uint32_t* timings = decoder->timings; - IrdaStatus status = IrdaStatusError; + IrdaStatus status = IrdaStatusOk; + const IrdaTimings* timings = &decoder->protocol->timings; + + while (decoder->timings_cnt && (status == IrdaStatusOk)) { + bool level = (decoder->level + decoder->timings_cnt + 1) % 2; + uint32_t timing = decoder->timings[0]; + + /* check if short protocol version can be decoded */ + if (timings->min_split_time && !level && (timing > timings->min_split_time)) { + for (int i = 1; decoder->protocol->databit_len[i] && (i < COUNT_OF(decoder->protocol->databit_len)); ++i) { + if (decoder->protocol->databit_len[i] == decoder->databit_cnt) { + return IrdaStatusReady; + } + } + } + + status = decoder->protocol->decode(decoder, level, timing); + furi_assert(status == IrdaStatusError || status == IrdaStatusOk); + if (status == IrdaStatusError) { + break; + } + decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); + + /* check if largest protocol version can be decoded */ + if (level && (decoder->protocol->databit_len[0] == decoder->databit_cnt)) { + status = IrdaStatusReady; + break; + } + } + + return status; +} + +/* Pulse Distance-Width Modulation */ +IrdaStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder, bool level, uint32_t timing) { + furi_assert(decoder); + + IrdaStatus status = IrdaStatusOk; uint32_t bit_tolerance = decoder->protocol->timings.bit_tolerance; uint16_t bit1_mark = decoder->protocol->timings.bit1_mark; uint16_t bit1_space = decoder->protocol->timings.bit1_space; uint16_t bit0_mark = decoder->protocol->timings.bit0_mark; uint16_t bit0_space = decoder->protocol->timings.bit0_space; - while (1) { - // Stop bit - if ((decoder->databit_cnt == decoder->protocol->databit_len) && (decoder->timings_cnt == 1)) { - if (MATCH_TIMING(timings[0], bit1_mark, bit_tolerance)) { - decoder->timings_cnt = 0; - status = IrdaStatusReady; - } else { - status = IrdaStatusError; - } - break; - } + bool analyze_timing = level ^ (bit1_mark == bit0_mark); + uint16_t bit1 = level ? bit1_mark : bit1_space; + uint16_t bit0 = level ? bit0_mark : bit0_space; + uint16_t no_info_timing = (bit1_mark == bit0_mark) ? bit1_mark : bit1_space; - if (decoder->timings_cnt >= 2) { - if (MATCH_TIMING(timings[0], bit1_mark, bit_tolerance) - && MATCH_TIMING(timings[1], bit1_space, bit_tolerance)) { - accumulate_lsb(decoder, 1); - } else if (MATCH_TIMING(timings[0], bit0_mark, bit_tolerance) - && MATCH_TIMING(timings[1], bit0_space, bit_tolerance)) { - accumulate_lsb(decoder, 0); - } else { - status = IrdaStatusError; - break; - } - decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 2); + if (analyze_timing) { + if (MATCH_TIMING(timing, bit1, bit_tolerance)) { + accumulate_lsb(decoder, 1); + } else if (MATCH_TIMING(timing, bit0, bit_tolerance)) { + accumulate_lsb(decoder, 0); } else { - status = IrdaStatusOk; - break; + status = IrdaStatusError; + } + } else { + if (!MATCH_TIMING(timing, no_info_timing, bit_tolerance)) { + status = IrdaStatusError; } } @@ -112,111 +144,59 @@ IrdaStatus irda_common_decode_pdm(IrdaCommonDecoder* decoder) { } /* level switch detection goes in middle of time-quant */ -IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { +IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder, bool level, uint32_t timing) { furi_assert(decoder); - IrdaStatus status = IrdaStatusOk; uint16_t bit = decoder->protocol->timings.bit1_mark; uint16_t tolerance = decoder->protocol->timings.bit_tolerance; - while (decoder->timings_cnt) { - uint32_t timing = decoder->timings[0]; - bool* switch_detect = &decoder->switch_detect; - furi_assert((*switch_detect == true) || (*switch_detect == false)); + bool* switch_detect = &decoder->switch_detect; + furi_assert((*switch_detect == true) || (*switch_detect == false)); - bool single_timing = MATCH_TIMING(timing, bit, tolerance); - bool double_timing = MATCH_TIMING(timing, 2*bit, tolerance); + bool single_timing = MATCH_TIMING(timing, bit, tolerance); + bool double_timing = MATCH_TIMING(timing, 2*bit, tolerance); - if(!single_timing && !double_timing) { - status = IrdaStatusError; - break; - } - - if ((decoder->protocol->manchester_start_from_space) && (decoder->databit_cnt == 0)) { - *switch_detect = 1; /* fake as we were previously in the middle of time-quant */ - decoder->data[0] = 0; /* first captured timing should be Mark */ - ++decoder->databit_cnt; - } - - if (*switch_detect == 0) { - if (double_timing) { - status = IrdaStatusError; - break; - } - /* only single timing - level switch required in the middle of time-quant */ - *switch_detect = 1; - } else { - /* double timing means we in the middle of time-quant again */ - if (single_timing) - *switch_detect = 0; - } - - decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); - status = IrdaStatusOk; - bool level = (decoder->level + decoder->timings_cnt) % 2; - - if (decoder->databit_cnt < decoder->protocol->databit_len) { - if (*switch_detect) { - accumulate_lsb(decoder, level); - } - if (decoder->databit_cnt == decoder->protocol->databit_len) { - if (level) { - status = IrdaStatusReady; - break; - } - } - } else { - furi_assert(level); - /* cover case: sequence should be stopped after last bit was received */ - if (single_timing) { - status = IrdaStatusReady; - break; - } else { - status = IrdaStatusError; - } - } + if(!single_timing && !double_timing) { + return IrdaStatusError; } - return status; + if (decoder->protocol->manchester_start_from_space && (decoder->databit_cnt == 0)) { + *switch_detect = 1; /* fake as we were previously in the middle of time-quant */ + accumulate_lsb(decoder, 0); + } + + if (*switch_detect == 0) { + if (double_timing) { + return IrdaStatusError; + } + /* only single timing - level switch required in the middle of time-quant */ + *switch_detect = 1; + } else { + /* double timing means we're in the middle of time-quant again */ + if (single_timing) + *switch_detect = 0; + } + + if (*switch_detect) { + accumulate_lsb(decoder, level); + } + + return IrdaStatusOk; } -/* Pulse Width Modulation */ -IrdaStatus irda_common_decode_pwm(IrdaCommonDecoder* decoder) { - furi_assert(decoder); +IrdaMessage* irda_common_decoder_check_ready(IrdaCommonDecoder* decoder) { + IrdaMessage* message = NULL; - uint32_t* timings = decoder->timings; - IrdaStatus status = IrdaStatusOk; - uint32_t bit_tolerance = decoder->protocol->timings.bit_tolerance; - uint16_t bit1_mark = decoder->protocol->timings.bit1_mark; - uint16_t bit1_space = decoder->protocol->timings.bit1_space; - uint16_t bit0_mark = decoder->protocol->timings.bit0_mark; - - while (decoder->timings_cnt) { - bool level = (decoder->level + decoder->timings_cnt + 1) % 2; - - if (level) { - if (MATCH_TIMING(timings[0], bit1_mark, bit_tolerance)) { - accumulate_lsb(decoder, 1); - } else if (MATCH_TIMING(timings[0], bit0_mark, bit_tolerance)) { - accumulate_lsb(decoder, 0); - } else { - status = IrdaStatusError; - break; - } + if (decoder->protocol->interpret(decoder)) { + decoder->databit_cnt = 0; + message = &decoder->message; + if (decoder->protocol->decode_repeat) { + decoder->state = IrdaCommonDecoderStateProcessRepeat; } else { - if (!MATCH_TIMING(timings[0], bit1_space, bit_tolerance)) { - status = IrdaStatusError; - break; - } - } - decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); - - if (decoder->databit_cnt == decoder->protocol->databit_len) { - status = IrdaStatusReady; - break; + decoder->state = IrdaCommonDecoderStateWaitPreamble; } } - return status; + return message; } IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t duration) { @@ -245,12 +225,13 @@ IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t } break; case IrdaCommonDecoderStateDecode: - status = decoder->protocol->decode(decoder); + status = irda_common_decode_bits(decoder); if (status == IrdaStatusReady) { - if (decoder->protocol->interpret(decoder)) { - message = &decoder->message; - decoder->state = IrdaCommonDecoderStateProcessRepeat; - } else { + message = irda_common_decoder_check_ready(decoder); + if (message) { + continue; + } else if (decoder->protocol->databit_len[0] == decoder->databit_cnt) { + /* error: can't decode largest protocol - begin decoding from start */ decoder->state = IrdaCommonDecoderStateWaitPreamble; } } else if (status == IrdaStatusError) { @@ -259,10 +240,6 @@ IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t } break; case IrdaCommonDecoderStateProcessRepeat: - if (!decoder->protocol->decode_repeat) { - decoder->state = IrdaCommonDecoderStateWaitPreamble; - continue; - } status = decoder->protocol->decode_repeat(decoder); if (status == IrdaStatusError) { irda_common_decoder_reset_state(decoder); @@ -282,9 +259,14 @@ IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec* protocol) { furi_assert(protocol); + /* protocol->databit_len[0] has to contain biggest value of bits that can be decoded */ + for (int i = 1; i < COUNT_OF(protocol->databit_len); ++i) { + furi_assert(protocol->databit_len[i] <= protocol->databit_len[0]); + } + uint32_t alloc_size = sizeof(IrdaCommonDecoder) - + protocol->databit_len / 8 - + !!(protocol->databit_len % 8); + + protocol->databit_len[0] / 8 + + !!(protocol->databit_len[0] % 8); IrdaCommonDecoder* decoder = furi_alloc(alloc_size); memset(decoder, 0, alloc_size); decoder->protocol = protocol; diff --git a/lib/irda/encoder_decoder/common/irda_common_encoder.c b/lib/irda/encoder_decoder/common/irda_common_encoder.c index cdb65d0a..aefbda35 100644 --- a/lib/irda/encoder_decoder/common/irda_common_encoder.c +++ b/lib/irda/encoder_decoder/common/irda_common_encoder.c @@ -4,6 +4,19 @@ #include #include #include "irda_i.h" +#include + +static IrdaStatus irda_common_encode_bits(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { + IrdaStatus status = encoder->protocol->encode(encoder, duration, level); + furi_assert(status == IrdaStatusOk); + ++encoder->timings_encoded; + encoder->timings_sum += *duration; + if ((encoder->bits_encoded == encoder->bits_to_encode) && *level) { + status = IrdaStatusDone; + } + + return status; +} /* * @@ -32,14 +45,12 @@ IrdaStatus irda_common_encode_manchester(IrdaCommonEncoder* encoder, uint32_t* d *level = even_timing ^ logic_value; *duration = timings->bit1_mark; - if (even_timing) /* start encoding from space */ + if (even_timing) ++encoder->bits_encoded; - ++encoder->timings_encoded; - encoder->timings_sum += *duration; + else if (*level && (encoder->bits_encoded + 1 == encoder->bits_to_encode)) + ++encoder->bits_encoded; /* don't encode last space */ - bool finish = (encoder->bits_encoded == encoder->protocol->databit_len); - finish |= (encoder->bits_encoded == (encoder->protocol->databit_len-1)) && *level && !even_timing; - return finish ? IrdaStatusDone : IrdaStatusOk; + return IrdaStatusOk; } IrdaStatus irda_common_encode_pdwm(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { @@ -47,39 +58,25 @@ IrdaStatus irda_common_encode_pdwm(IrdaCommonEncoder* encoder, uint32_t* duratio furi_assert(duration); furi_assert(level); - bool done = false; const IrdaTimings* timings = &encoder->protocol->timings; uint8_t index = encoder->bits_encoded / 8; uint8_t shift = encoder->bits_encoded % 8; // LSB first bool logic_value = !!(encoder->data[index] & (0x01 << shift)); - - // stop bit - if (encoder->bits_encoded == encoder->protocol->databit_len) { - furi_assert(!encoder->protocol->no_stop_bit); - *duration = timings->bit1_mark; - *level = true; - ++encoder->timings_encoded; - encoder->timings_sum += *duration; - return IrdaStatusDone; - } + bool pwm = timings->bit1_space == timings->bit0_space; if (encoder->timings_encoded % 2) { /* start encoding from space */ *duration = logic_value ? timings->bit1_mark : timings->bit0_mark; *level = true; + if (pwm) + ++encoder->bits_encoded; } else { *duration = logic_value ? timings->bit1_space : timings->bit0_space; *level = false; - ++encoder->bits_encoded; + if (!pwm) + ++encoder->bits_encoded; } - if ((encoder->bits_encoded == encoder->protocol->databit_len) - && encoder->protocol->no_stop_bit) { - done = true; - } - - ++encoder->timings_encoded; - encoder->timings_sum += *duration; - return done ? IrdaStatusDone : IrdaStatusOk; + return IrdaStatusOk; } IrdaStatus irda_common_encode(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { @@ -116,7 +113,7 @@ IrdaStatus irda_common_encode(IrdaCommonEncoder* encoder, uint32_t* duration, bo } /* FALLTHROUGH */ case IrdaCommonEncoderStateEncode: - status = encoder->protocol->encode(encoder, duration, level); + status = irda_common_encode_bits(encoder, duration, level); if (status == IrdaStatusDone) { if (encoder->protocol->encode_repeat) { encoder->state = IrdaCommonEncoderStateEncodeRepeat; @@ -138,10 +135,18 @@ IrdaStatus irda_common_encode(IrdaCommonEncoder* encoder, uint32_t* duration, bo void* irda_common_encoder_alloc(const IrdaCommonProtocolSpec* protocol) { furi_assert(protocol); + if (protocol->decode == irda_common_decode_pdwm) { + furi_assert((protocol->timings.bit1_mark == protocol->timings.bit0_mark) ^ (protocol->timings.bit1_space == protocol->timings.bit0_space)); + } - uint32_t alloc_size = sizeof(IrdaCommonEncoder) - + protocol->databit_len / 8 - + !!(protocol->databit_len % 8); + /* protocol->databit_len[0] has to contain biggest value of bits that can be decoded */ + for (int i = 1; i < COUNT_OF(protocol->databit_len); ++i) { + furi_assert(protocol->databit_len[i] <= protocol->databit_len[0]); + } + + uint32_t alloc_size = sizeof(IrdaCommonDecoder) + + protocol->databit_len[0] / 8 + + !!(protocol->databit_len[0] % 8); IrdaCommonEncoder* encoder = furi_alloc(alloc_size); memset(encoder, 0, alloc_size); encoder->protocol = protocol; @@ -162,8 +167,14 @@ void irda_common_encoder_reset(IrdaCommonEncoder* encoder) { encoder->state = IrdaCommonEncoderStateSilence; encoder->switch_detect = 0; - uint8_t bytes_to_clear = encoder->protocol->databit_len / 8 - + !!(encoder->protocol->databit_len % 8); + uint8_t max_databit_len = 0; + + for (int i = 0; i < COUNT_OF(encoder->protocol->databit_len); ++i) { + max_databit_len = MAX(max_databit_len, encoder->protocol->databit_len[i]); + } + + uint8_t bytes_to_clear = max_databit_len / 8 + + !!(max_databit_len % 8); memset(encoder->data, 0, bytes_to_clear); } diff --git a/lib/irda/encoder_decoder/common/irda_common_i.h b/lib/irda/encoder_decoder/common/irda_common_i.h index 5cf7b584..d7510617 100644 --- a/lib/irda/encoder_decoder/common/irda_common_i.h +++ b/lib/irda/encoder_decoder/common/irda_common_i.h @@ -11,7 +11,8 @@ typedef struct IrdaCommonDecoder IrdaCommonDecoder; typedef struct IrdaCommonEncoder IrdaCommonEncoder; -typedef IrdaStatus (*IrdaCommonDecode)(IrdaCommonDecoder*); +typedef IrdaStatus (*IrdaCommonDecode)(IrdaCommonDecoder*, bool, uint32_t); +typedef IrdaStatus (*IrdaCommonDecodeRepeat)(IrdaCommonDecoder*); typedef bool (*IrdaCommonInterpret)(IrdaCommonDecoder*); typedef IrdaStatus (*IrdaCommonEncode)(IrdaCommonEncoder* encoder, uint32_t* out, bool* polarity); @@ -19,9 +20,9 @@ typedef struct { IrdaTimings timings; bool manchester_start_from_space; bool no_stop_bit; - uint32_t databit_len; + uint8_t databit_len[4]; IrdaCommonDecode decode; - IrdaCommonDecode decode_repeat; + IrdaCommonDecodeRepeat decode_repeat; IrdaCommonInterpret interpret; IrdaCommonEncode encode; IrdaCommonEncode encode_repeat; @@ -57,7 +58,8 @@ struct IrdaCommonEncoder { const IrdaCommonProtocolSpec* protocol; IrdaCommonStateEncoder state; bool switch_detect; - uint32_t bits_encoded; + uint8_t bits_to_encode; + uint8_t bits_encoded; uint32_t timings_sum; uint32_t timings_encoded; void* context; @@ -65,12 +67,12 @@ struct IrdaCommonEncoder { }; IrdaMessage* irda_common_decode(IrdaCommonDecoder *decoder, bool level, uint32_t duration); -IrdaStatus irda_common_decode_pdm(IrdaCommonDecoder* decoder); -IrdaStatus irda_common_decode_pwm(IrdaCommonDecoder* decoder); -IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder); +IrdaStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder, bool level, uint32_t timing); +IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder, bool level, uint32_t timing); void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec *protocol); void irda_common_decoder_free(IrdaCommonDecoder* decoder); void irda_common_decoder_reset(IrdaCommonDecoder* decoder); +IrdaMessage* irda_common_decoder_check_ready(IrdaCommonDecoder* decoder); IrdaStatus irda_common_encode(IrdaCommonEncoder* encoder, uint32_t* duration, bool* polarity); IrdaStatus irda_common_encode_pdwm(IrdaCommonEncoder* encoder, uint32_t* duration, bool* polarity); diff --git a/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c b/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c index 75e3b604..61744887 100644 --- a/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c +++ b/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c @@ -12,10 +12,12 @@ const IrdaCommonProtocolSpec protocol_nec = { .preamble_tolerance = IRDA_NEC_PREAMBLE_TOLERANCE, .bit_tolerance = IRDA_NEC_BIT_TOLERANCE, .silence_time = IRDA_NEC_SILENCE, + .min_split_time = IRDA_NEC_MIN_SPLIT_TIME, }, - .databit_len = 32, + .databit_len[0] = 42, + .databit_len[1] = 32, .no_stop_bit = false, - .decode = irda_common_decode_pdm, + .decode = irda_common_decode_pdwm, .encode = irda_common_encode_pdwm, .interpret = irda_decoder_nec_interpret, .decode_repeat = irda_decoder_nec_decode_repeat, @@ -34,9 +36,9 @@ const IrdaCommonProtocolSpec protocol_samsung32 = { .bit_tolerance = IRDA_SAMSUNG_BIT_TOLERANCE, .silence_time = IRDA_SAMSUNG_SILENCE, }, - .databit_len = 32, + .databit_len[0] = 32, .no_stop_bit = false, - .decode = irda_common_decode_pdm, + .decode = irda_common_decode_pdwm, .encode = irda_common_encode_pdwm, .interpret = irda_decoder_samsung32_interpret, .decode_repeat = irda_decoder_samsung32_decode_repeat, @@ -52,7 +54,7 @@ const IrdaCommonProtocolSpec protocol_rc6 = { .bit_tolerance = IRDA_RC6_BIT_TOLERANCE, .silence_time = IRDA_RC6_SILENCE, }, - .databit_len = 1 + 3 + 1 + 8 + 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command + .databit_len[0] = 1 + 3 + 1 + 8 + 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command .manchester_start_from_space = false, .decode = irda_decoder_rc6_decode_manchester, .encode = irda_encoder_rc6_encode_manchester, @@ -70,7 +72,7 @@ const IrdaCommonProtocolSpec protocol_rc5 = { .bit_tolerance = IRDA_RC5_BIT_TOLERANCE, .silence_time = IRDA_RC5_SILENCE, }, - .databit_len = 1 + 1 + 1 + 5 + 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command + .databit_len[0] = 1 + 1 + 1 + 5 + 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command .manchester_start_from_space = true, .decode = irda_common_decode_manchester, .encode = irda_common_encode_manchester, @@ -90,10 +92,13 @@ const IrdaCommonProtocolSpec protocol_sirc = { .preamble_tolerance = IRDA_SIRC_PREAMBLE_TOLERANCE, .bit_tolerance = IRDA_SIRC_BIT_TOLERANCE, .silence_time = IRDA_SIRC_SILENCE, + .min_split_time = IRDA_SIRC_MIN_SPLIT_TIME, }, - .databit_len = 20, /* 12/15/20 */ + .databit_len[0] = 20, + .databit_len[1] = 15, + .databit_len[2] = 12, .no_stop_bit = true, - .decode = irda_common_decode_pwm, + .decode = irda_common_decode_pdwm, .encode = irda_common_encode_pdwm, .interpret = irda_decoder_sirc_interpret, .decode_repeat = NULL, diff --git a/lib/irda/encoder_decoder/irda.c b/lib/irda/encoder_decoder/irda.c index 73bd4f5e..19a4df46 100644 --- a/lib/irda/encoder_decoder/irda.c +++ b/lib/irda/encoder_decoder/irda.c @@ -45,6 +45,7 @@ static const IrdaEncoderDecoder irda_encoder_decoder[] = { .alloc = irda_decoder_nec_alloc, .decode = irda_decoder_nec_decode, .reset = irda_decoder_nec_reset, + .check_ready = irda_decoder_nec_check_ready, .free = irda_decoder_nec_free}, .encoder = { .alloc = irda_encoder_nec_alloc, diff --git a/lib/irda/encoder_decoder/irda.h b/lib/irda/encoder_decoder/irda.h index 25a13528..c6151cac 100644 --- a/lib/irda/encoder_decoder/irda.h +++ b/lib/irda/encoder_decoder/irda.h @@ -21,14 +21,16 @@ typedef struct IrdaEncoderHandler IrdaEncoderHandler; typedef enum { IrdaProtocolUnknown = -1, IrdaProtocolNEC = 0, - IrdaProtocolNECext = 1, - IrdaProtocolSamsung32 = 2, - IrdaProtocolRC6 = 3, - IrdaProtocolRC5 = 4, - IrdaProtocolRC5X = 5, - IrdaProtocolSIRC = 6, - IrdaProtocolSIRC15 = 7, - IrdaProtocolSIRC20 = 8, + IrdaProtocolNECext, + IrdaProtocolNEC42, + IrdaProtocolNEC42ext, + IrdaProtocolSamsung32, + IrdaProtocolRC6, + IrdaProtocolRC5, + IrdaProtocolRC5X, + IrdaProtocolSIRC, + IrdaProtocolSIRC15, + IrdaProtocolSIRC20, IrdaProtocolMAX, } IrdaProtocol; diff --git a/lib/irda/encoder_decoder/irda_i.h b/lib/irda/encoder_decoder/irda_i.h index c147b3db..e90e3a3b 100644 --- a/lib/irda/encoder_decoder/irda_i.h +++ b/lib/irda/encoder_decoder/irda_i.h @@ -4,6 +4,7 @@ #include typedef struct { + uint32_t min_split_time; uint32_t silence_time; uint16_t preamble_mark; uint16_t preamble_space; diff --git a/lib/irda/encoder_decoder/irda_protocol_defs_i.h b/lib/irda/encoder_decoder/irda_protocol_defs_i.h index 15d9fea2..4c380160 100644 --- a/lib/irda/encoder_decoder/irda_protocol_defs_i.h +++ b/lib/irda/encoder_decoder/irda_protocol_defs_i.h @@ -23,12 +23,13 @@ #define IRDA_NEC_PREAMBLE_MARK 9000 #define IRDA_NEC_PREAMBLE_SPACE 4500 #define IRDA_NEC_BIT1_MARK 560 -#define IRDA_NEC_BIT1_SPACE 1600 +#define IRDA_NEC_BIT1_SPACE 1690 #define IRDA_NEC_BIT0_MARK 560 #define IRDA_NEC_BIT0_SPACE 560 #define IRDA_NEC_REPEAT_PERIOD 110000 #define IRDA_NEC_SILENCE IRDA_NEC_REPEAT_PERIOD -#define IRDA_NEC_REPEAT_PAUSE_MIN 30000 +#define IRDA_NEC_MIN_SPLIT_TIME IRDA_NEC_REPEAT_PAUSE_MIN +#define IRDA_NEC_REPEAT_PAUSE_MIN 4000 #define IRDA_NEC_REPEAT_PAUSE_MAX 150000 #define IRDA_NEC_REPEAT_MARK 9000 #define IRDA_NEC_REPEAT_SPACE 2250 @@ -38,6 +39,7 @@ void* irda_decoder_nec_alloc(void); void irda_decoder_nec_reset(void* decoder); void irda_decoder_nec_free(void* decoder); +IrdaMessage* irda_decoder_nec_check_ready(void* decoder); IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); void* irda_encoder_nec_alloc(void); IrdaStatus irda_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); @@ -143,7 +145,7 @@ void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message); void irda_encoder_rc6_free(void* decoder); IrdaStatus irda_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder); -IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder); +IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder, bool level, uint32_t timing); IrdaStatus irda_encoder_rc6_encode_manchester(IrdaCommonEncoder* encoder_ptr, uint32_t* duration, bool* polarity); const IrdaProtocolSpecification* irda_rc6_get_spec(IrdaProtocol protocol); @@ -229,7 +231,7 @@ extern const IrdaCommonProtocolSpec protocol_rc5; #define IRDA_SIRC_PREAMBLE_TOLERANCE 200 // us #define IRDA_SIRC_BIT_TOLERANCE 120 // us #define IRDA_SIRC_SILENCE 10000 -#define IRDA_SIRC_MIN_SILENCE (IRDA_SIRC_SILENCE - 1000) +#define IRDA_SIRC_MIN_SPLIT_TIME (IRDA_SIRC_SILENCE - 1000) #define IRDA_SIRC_REPEAT_PERIOD 45000 diff --git a/lib/irda/encoder_decoder/nec/irda_decoder_nec.c b/lib/irda/encoder_decoder/nec/irda_decoder_nec.c index 79a85d76..541e98f3 100644 --- a/lib/irda/encoder_decoder/nec/irda_decoder_nec.c +++ b/lib/irda/encoder_decoder/nec/irda_decoder_nec.c @@ -1,3 +1,4 @@ +#include "common/irda_common_i.h" #include "irda.h" #include "irda_protocol_defs_i.h" #include @@ -6,26 +7,55 @@ #include "../irda_i.h" +IrdaMessage* irda_decoder_nec_check_ready(void* ctx) { + return irda_common_decoder_check_ready(ctx); +} + bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder) { furi_assert(decoder); bool result = false; - uint8_t address = decoder->data[0]; - uint8_t address_inverse = decoder->data[1]; - uint8_t command = decoder->data[2]; - uint8_t command_inverse = decoder->data[3]; - if (command == (uint8_t) ~command_inverse) { - if (address == (uint8_t) ~address_inverse) { + if (decoder->databit_cnt == 32) { + uint8_t address = decoder->data[0]; + uint8_t address_inverse = decoder->data[1]; + uint8_t command = decoder->data[2]; + uint8_t command_inverse = decoder->data[3]; + if ((command == (uint8_t) ~command_inverse) && (address == (uint8_t) ~address_inverse)) { decoder->message.protocol = IrdaProtocolNEC; decoder->message.address = address; + decoder->message.command = command; + decoder->message.repeat = false; + result = true; } else { decoder->message.protocol = IrdaProtocolNECext; decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); + decoder->message.command = decoder->data[2] | (decoder->data[3] << 8); + decoder->message.repeat = false; + result = true; + } + } else if (decoder->databit_cnt == 42) { + uint32_t* data1 = (void*) decoder->data; + uint16_t* data2 = (void*) (data1 + 1); + uint16_t address = *data1 & 0x1FFF; + uint16_t address_inverse = (*data1 >> 13) & 0x1FFF; + uint16_t command = ((*data1 >> 26) & 0x3F) | ((*data2 & 0x3) << 6); + uint16_t command_inverse = (*data2 >> 2) & 0xFF; + + if ((address == (~address_inverse & 0x1FFF)) + && (command == (~command_inverse & 0xFF))) { + decoder->message.protocol = IrdaProtocolNEC42; + decoder->message.address = address; + decoder->message.command = command; + decoder->message.repeat = false; + result = true; + } else { + decoder->message.protocol = IrdaProtocolNEC42ext; + decoder->message.address = address | (address_inverse << 13); + decoder->message.command = command | (command_inverse << 8); + decoder->message.repeat = false; + result = true; } - decoder->message.command = command; - decoder->message.repeat = false; - result = true; } return result; diff --git a/lib/irda/encoder_decoder/nec/irda_encoder_nec.c b/lib/irda/encoder_decoder/nec/irda_encoder_nec.c index b6551b77..137a3be6 100644 --- a/lib/irda/encoder_decoder/nec/irda_encoder_nec.c +++ b/lib/irda/encoder_decoder/nec/irda_encoder_nec.c @@ -20,26 +20,45 @@ void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { IrdaCommonEncoder* encoder = encoder_ptr; irda_common_encoder_reset(encoder); - uint8_t address = message->address; - uint8_t address_inverse = ~address; - uint8_t command = message->command; - uint8_t command_inverse = ~command; - - uint32_t* data = (void*) encoder->data; + uint32_t* data1 = (void*) encoder->data; + uint32_t* data2 = data1 + 1; if (message->protocol == IrdaProtocolNEC) { - *data = (address | (address_inverse << 8)); + uint8_t address = message->address; + uint8_t address_inverse = ~address; + uint8_t command = message->command; + uint8_t command_inverse = ~command; + *data1 = address; + *data1 |= address_inverse << 8; + *data1 |= command << 16; + *data1 |= command_inverse << 24; + encoder->bits_to_encode = 32; } else if (message->protocol == IrdaProtocolNECext) { - *data = (uint16_t) message->address; + *data1 = (uint16_t) message->address; + *data1 |= (message->command & 0xFFFF) << 16; + encoder->bits_to_encode = 32; + } else if (message->protocol == IrdaProtocolNEC42) { + /* 13 address + 13 inverse address + 8 command + 8 inv command */ + *data1 = message->address & 0x1FFFUL; + *data1 |= (~message->address & 0x1FFFUL) << 13; + *data1 |= ((message->command & 0x3FUL) << 26); + *data2 = (message->command & 0xC0UL) >> 6; + *data2 |= (~message->command & 0xFFUL) << 2; + encoder->bits_to_encode = 42; + } else if (message->protocol == IrdaProtocolNEC42ext) { + *data1 = message->address & 0x3FFFFFF; + *data1 |= ((message->command & 0x3F) << 26); + *data2 = (message->command & 0xFFC0) >> 6; + encoder->bits_to_encode = 42; + } else { + furi_assert(0); } - *data |= command << 16; - *data |= command_inverse << 24; } IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { furi_assert(encoder); /* space + 2 timings preambule + payload + stop bit */ - uint32_t timings_encoded_up_to_repeat = 1 + 2 + encoder->protocol->databit_len * 2 + 1; + uint32_t timings_encoded_up_to_repeat = 1 + 2 + encoder->bits_to_encode * 2 + 1; uint32_t repeat_cnt = encoder->timings_encoded - timings_encoded_up_to_repeat; furi_assert(encoder->timings_encoded >= timings_encoded_up_to_repeat); diff --git a/lib/irda/encoder_decoder/nec/irda_nec_spec.c b/lib/irda/encoder_decoder/nec/irda_nec_spec.c index 9c27b69a..0460caec 100644 --- a/lib/irda/encoder_decoder/nec/irda_nec_spec.c +++ b/lib/irda/encoder_decoder/nec/irda_nec_spec.c @@ -12,16 +12,36 @@ static const IrdaProtocolSpecification irda_nec_protocol_specification = { static const IrdaProtocolSpecification irda_necext_protocol_specification = { .name = "NECext", .address_length = 16, + .command_length = 16, + .frequency = IRDA_COMMON_CARRIER_FREQUENCY, + .duty_cycle = IRDA_COMMON_DUTY_CYCLE, +}; + +static const IrdaProtocolSpecification irda_nec42_protocol_specification = { + .name = "NEC42", + .address_length = 13, .command_length = 8, .frequency = IRDA_COMMON_CARRIER_FREQUENCY, .duty_cycle = IRDA_COMMON_DUTY_CYCLE, }; +static const IrdaProtocolSpecification irda_nec42ext_protocol_specification = { + .name = "NEC42ext", + .address_length = 26, + .command_length = 16, + .frequency = IRDA_COMMON_CARRIER_FREQUENCY, + .duty_cycle = IRDA_COMMON_DUTY_CYCLE, +}; + const IrdaProtocolSpecification* irda_nec_get_spec(IrdaProtocol protocol) { if (protocol == IrdaProtocolNEC) return &irda_nec_protocol_specification; else if (protocol == IrdaProtocolNECext) return &irda_necext_protocol_specification; + else if (protocol == IrdaProtocolNEC42) + return &irda_nec42_protocol_specification; + else if (protocol == IrdaProtocolNEC42ext) + return &irda_nec42ext_protocol_specification; else return NULL; } diff --git a/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c b/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c index e6fa9f0d..fb55788e 100644 --- a/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c +++ b/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c @@ -30,6 +30,7 @@ void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message) { common_encoder->data[0] = ~common_encoder->data[0]; common_encoder->data[1] = ~common_encoder->data[1]; + common_encoder->bits_to_encode = common_encoder->protocol->databit_len[0]; encoder->toggle_bit ^= 1; } diff --git a/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c b/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c index 9bab9da0..cedc617f 100644 --- a/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c +++ b/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c @@ -50,39 +50,35 @@ bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder) { * it separately and than pass decoding for other bits to * common manchester decode function. */ -IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder) { +IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder, bool level, uint32_t timing) { // 4th bit lasts 2x times more IrdaStatus status = IrdaStatusError; uint16_t bit = decoder->protocol->timings.bit1_mark; uint16_t tolerance = decoder->protocol->timings.bit_tolerance; - uint16_t timing = decoder->timings[0]; bool single_timing = MATCH_TIMING(timing, bit, tolerance); bool double_timing = MATCH_TIMING(timing, 2*bit, tolerance); bool triple_timing = MATCH_TIMING(timing, 3*bit, tolerance); if (decoder->databit_cnt == 4) { - furi_assert(decoder->timings_cnt == 1); furi_assert(decoder->switch_detect == true); if (single_timing ^ triple_timing) { - --decoder->timings_cnt; ++decoder->databit_cnt; - decoder->data[0] |= (single_timing ? !decoder->level : decoder->level) << 4; + decoder->data[0] |= (single_timing ? !level : level) << 4; status = IrdaStatusOk; } } else if (decoder->databit_cnt == 5) { if (single_timing || triple_timing) { if (triple_timing) - decoder->timings[0] = bit; + timing = bit; decoder->switch_detect = false; - status = irda_common_decode_manchester(decoder); + status = irda_common_decode_manchester(decoder, level, timing); } else if (double_timing) { - --decoder->timings_cnt; status = IrdaStatusOk; } } else { - status = irda_common_decode_manchester(decoder); + status = irda_common_decode_manchester(decoder, level, timing); } return status; diff --git a/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c b/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c index 2d099b7d..23063c24 100644 --- a/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c +++ b/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c @@ -24,6 +24,7 @@ void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message) { *data |= reverse(message->address) << 5; *data |= reverse(message->command) << 13; + common_encoder->bits_to_encode = common_encoder->protocol->databit_len[0]; encoder->toggle_bit ^= 1; } diff --git a/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c b/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c index 5a3c5f50..9ee17d4a 100644 --- a/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c +++ b/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c @@ -29,13 +29,15 @@ void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message) *data |= address << 8; *data |= command << 16; *data |= command_inverse << 24; + + encoder->bits_to_encode = encoder->protocol->databit_len[0]; } IrdaStatus irda_encoder_samsung32_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { furi_assert(encoder); /* space + 2 timings preambule + payload + stop bit */ - uint32_t timings_encoded_up_to_repeat = 1 + 2 + encoder->protocol->databit_len * 2 + 1; + uint32_t timings_encoded_up_to_repeat = 1 + 2 + encoder->bits_encoded * 2 + 1; uint32_t repeat_cnt = encoder->timings_encoded - timings_encoded_up_to_repeat; furi_assert(encoder->timings_encoded >= timings_encoded_up_to_repeat); diff --git a/lib/irda/encoder_decoder/sirc/irda_decoder_sirc.c b/lib/irda/encoder_decoder/sirc/irda_decoder_sirc.c index 2ae76863..00b49eef 100644 --- a/lib/irda/encoder_decoder/sirc/irda_decoder_sirc.c +++ b/lib/irda/encoder_decoder/sirc/irda_decoder_sirc.c @@ -8,16 +8,7 @@ IrdaMessage* irda_decoder_sirc_check_ready(void* ctx) { - IrdaMessage* message = NULL; - IrdaCommonDecoder* decoder = ctx; - - if (irda_decoder_sirc_interpret(decoder)) { - message = &decoder->message; - decoder->timings_cnt = 0; - decoder->databit_cnt = 0; - } - - return message; + return irda_common_decoder_check_ready(ctx); } bool irda_decoder_sirc_interpret(IrdaCommonDecoder* decoder) { @@ -57,29 +48,8 @@ void* irda_decoder_sirc_alloc(void) { return irda_common_decoder_alloc(&protocol_sirc); } -IrdaMessage* irda_decoder_sirc_decode(void* context, bool level, uint32_t duration) { - IrdaCommonDecoder* decoder = context; - IrdaMessage* message = NULL; - - if ((decoder->databit_cnt == 12) || (decoder->databit_cnt == 15)) { - if (!level && (duration >= IRDA_SIRC_MIN_SILENCE)) { - if (irda_decoder_sirc_interpret(decoder)) { - message = &decoder->message; - decoder->timings_cnt = 0; - decoder->databit_cnt = 0; - } - } - } - - if (!message) { - message = irda_common_decode(decoder, level, duration); - if (message) { /* 20 bit */ - decoder->timings_cnt = 0; - decoder->databit_cnt = 0; - } - } - - return message; +IrdaMessage* irda_decoder_sirc_decode(void* decoder, bool level, uint32_t duration) { + return irda_common_decode(decoder, level, duration); } void irda_decoder_sirc_free(void* decoder) { diff --git a/lib/irda/encoder_decoder/sirc/irda_encoder_sirc.c b/lib/irda/encoder_decoder/sirc/irda_encoder_sirc.c index d6cd54cf..ca98e830 100644 --- a/lib/irda/encoder_decoder/sirc/irda_encoder_sirc.c +++ b/lib/irda/encoder_decoder/sirc/irda_encoder_sirc.c @@ -7,34 +7,27 @@ #include -typedef struct { - IrdaCommonEncoder* common_encoder; - uint8_t databits; -} IrdaSircEncoder; - - void irda_encoder_sirc_reset(void* encoder_ptr, const IrdaMessage* message) { furi_assert(encoder_ptr); furi_assert(message); IrdaCommonEncoder* encoder = encoder_ptr; - IrdaSircEncoder* encoder_sirc = encoder->context; irda_common_encoder_reset(encoder); uint32_t* data = (void*) encoder->data; if (message->protocol == IrdaProtocolSIRC) { - encoder_sirc->databits = 12; *data = (message->command & 0x7F); *data |= (message->address & 0x1F) << 7; + encoder->bits_to_encode = 12; } else if (message->protocol == IrdaProtocolSIRC15) { - encoder_sirc->databits = 15; *data = (message->command & 0x7F); *data |= (message->address & 0xFF) << 7; + encoder->bits_to_encode = 15; } else if (message->protocol == IrdaProtocolSIRC20) { - encoder_sirc->databits = 20; *data = (message->command & 0x7F); *data |= (message->address & 0x1FFF) << 7; + encoder->bits_to_encode = 20; } else { furi_assert(0); } @@ -43,9 +36,7 @@ void irda_encoder_sirc_reset(void* encoder_ptr, const IrdaMessage* message) { IrdaStatus irda_encoder_sirc_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level) { furi_assert(encoder); - IrdaSircEncoder* encoder_sirc = encoder->context; - - uint32_t timings_in_message = 1 + 2 + encoder_sirc->databits * 2; + uint32_t timings_in_message = 1 + 2 + encoder->bits_to_encode * 2 - 1; furi_assert(encoder->timings_encoded == timings_in_message); furi_assert(encoder->timings_sum < IRDA_SIRC_REPEAT_PERIOD); @@ -61,28 +52,21 @@ IrdaStatus irda_encoder_sirc_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* } void* irda_encoder_sirc_alloc(void) { - IrdaCommonEncoder* encoder_common = irda_common_encoder_alloc(&protocol_sirc); - IrdaSircEncoder* encoder_sirc = furi_alloc(sizeof(IrdaSircEncoder)); - encoder_sirc->common_encoder = encoder_common; - encoder_common->context = encoder_sirc; - return encoder_common; + return irda_common_encoder_alloc(&protocol_sirc); } void irda_encoder_sirc_free(void* encoder_ptr) { - IrdaCommonEncoder* encoder = encoder_ptr; - free(encoder->context); - irda_common_encoder_free(encoder); + irda_common_encoder_free(encoder_ptr); } IrdaStatus irda_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* level) { - IrdaCommonEncoder* encoder_common = encoder_ptr; - IrdaSircEncoder* encoder_sirc = encoder_common->context; + IrdaCommonEncoder* encoder = encoder_ptr; - IrdaStatus status = irda_common_encode(encoder_ptr, duration, level); - if ((status == IrdaStatusOk) && (encoder_common->bits_encoded == encoder_sirc->databits)) { + IrdaStatus status = irda_common_encode(encoder, duration, level); + if ((status == IrdaStatusOk) && (encoder->bits_encoded == encoder->bits_to_encode)) { furi_assert(!*level); status = IrdaStatusDone; - encoder_common->state = IrdaCommonEncoderStateEncodeRepeat; + encoder->state = IrdaCommonEncoderStateEncodeRepeat; } return status; }