Sfoglia il codice sorgente

[FL-1956] Fix long packets bug, fix Manchester overrun (#766)

Also fix RC6 test to detect this manchester bug
Albert Kharisov 4 anni fa
parent
commit
98830a8a41

+ 3 - 0
applications/tests/furi_record_test.c

@@ -11,4 +11,7 @@ void test_furi_create_open() {
     // 2. Open it
     // 2. Open it
     void* record = furi_record_open("test/holding");
     void* record = furi_record_open("test/holding");
     mu_assert_pointers_eq(record, &test_data);
     mu_assert_pointers_eq(record, &test_data);
+    furi_record_close("test/holding");
+
+    furi_record_destroy("test/holding");
 }
 }

+ 6 - 0
applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c

@@ -247,6 +247,11 @@ MU_TEST(test_decoder_necext1) {
     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1);
     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1);
 }
 }
 
 
+MU_TEST(test_decoder_long_packets_with_nec_start) {
+    RUN_DECODER(test_decoder_nec42ext_input1, test_decoder_nec42ext_expected1);
+    RUN_DECODER(test_decoder_nec42ext_input2, test_decoder_nec42ext_expected2);
+}
+
 MU_TEST(test_encoder_sirc) {
 MU_TEST(test_encoder_sirc) {
     RUN_ENCODER(test_encoder_sirc_input1, test_encoder_sirc_expected1);
     RUN_ENCODER(test_encoder_sirc_input1, test_encoder_sirc_expected1);
     RUN_ENCODER(test_encoder_sirc_input2, test_encoder_sirc_expected2);
     RUN_ENCODER(test_encoder_sirc_input2, test_encoder_sirc_expected2);
@@ -310,6 +315,7 @@ MU_TEST_SUITE(test_irda_decoder_encoder) {
     MU_RUN_TEST(test_decoder_rc6);
     MU_RUN_TEST(test_decoder_rc6);
     MU_RUN_TEST(test_encoder_rc6);
     MU_RUN_TEST(test_encoder_rc6);
     MU_RUN_TEST(test_decoder_unexpected_end_in_sequence);
     MU_RUN_TEST(test_decoder_unexpected_end_in_sequence);
+    MU_RUN_TEST(test_decoder_long_packets_with_nec_start);
     MU_RUN_TEST(test_decoder_nec);
     MU_RUN_TEST(test_decoder_nec);
     MU_RUN_TEST(test_decoder_samsung32);
     MU_RUN_TEST(test_decoder_samsung32);
     MU_RUN_TEST(test_decoder_necext1);
     MU_RUN_TEST(test_decoder_necext1);

+ 33 - 0
applications/tests/irda_decoder_encoder/test_data/irda_nec_test_data.srcdata

@@ -306,3 +306,36 @@ const IrdaMessage test_nec42ext[] = {
     {IrdaProtocolNEC42ext,     0x1555555,      0x5555,  true},
     {IrdaProtocolNEC42ext,     0x1555555,      0x5555,  true},
 };
 };
 
 
+const uint32_t test_decoder_nec42ext_input1[] = {
+2000000, 9000, 4500,    560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 8
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 16
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 24
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 32
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 40
+                        560, 560, 560, 560, 560,                                                            // 42
+};
+
+const uint32_t test_decoder_nec42ext_input2[] = {
+2000000, 9000, 4500,    560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 8
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 16
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 24
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 32
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 40
+                        560, 560, 560, 560, 560, 560, 560,                                                  // 43 - failed
+
+2000000, 9000, 4500,    560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 8
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 16
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 24
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 32
+                        560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,     // 40
+                        560, 560, 560, 560, 560, 10000, 560,                                                // 42 OK + 1 failed
+};
+
+const IrdaMessage test_decoder_nec42ext_expected1[] = {
+    {IrdaProtocolNEC42ext,     0x00,      0,  false},
+};
+
+const IrdaMessage test_decoder_nec42ext_expected2[] = {
+    {IrdaProtocolNEC42ext,     0x00,      0,  false},
+};
+

+ 79 - 29
applications/tests/irda_decoder_encoder/test_data/irda_rc6_test_data.srcdata

@@ -1,45 +1,95 @@
 /*
 /*
 _____---------______--____--__--__--____------____--__----____--__----__--__--____----____--__--__--__--__--___________
 _____---------______--____--__--__--____------____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
-_____---------______--____--__--__------____--____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   1   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
-_____---------______--____--__--__--____------____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
-_____---------______--____--__--__--____------____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
-_____---------______--____--__--__--____------____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
-_____---------______--____--__--__------____--____--__----____--__----__--__--____----____--__--__--__--__--___________
-                    | 1 | 0 | 0 | 0 |   1   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   93 A0 0
                       s  m2  m1  m0     T   |            address            |            command            |
                       s  m2  m1  m0     T   |            address            |            command            |
+// 93 A0 0
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888,
+// --__----__--__--
+// 0 | 0 | 1 | 1 | 1
+//444, 444, 888, 444, 444, 444, 444,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
+_____---------______--____--__--__------____--____--__----____--__----__--__--____----____--__--__--__--__--___________
+                    | 1 | 0 | 0 | 0 |   1   | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   93 A0 1
+// 93 A0 1
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888,
+//444, 444, 888, 444, 444, 444, 444,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
+_____---------______--____--__--__--____------____--__----____----____--__----____----____--__--__--__--__--___________
+                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   94 A0 0
+// 94 A0 0
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 888, 888, 444, 444, 888, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888,
+//----____--__----
+//0 | 1 | 0 | 0 | 1
+//888, 888, 444, 444, 888,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
+_____---------______--____--__--__------____--____--__----____----____--__----____----____--__--__--__--__--___________
+                    | 1 | 0 | 0 | 0 |   1   | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   94 A0 1
+// 94 A0 1
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 888, 888, 444, 444, 888, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888,
+//888, 888, 444, 444, 888,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
+_____---------______--____--__--__--____------____--__----____----____----__--____----____--__--__--__--__--___________
+                    | 1 | 0 | 0 | 0 |   0   | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   95 A0 0
+// 95 A0 0
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 888, 888, 888, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888,
+//----____----__--
+//0 | 1 | 0 | 1 | 1
+//888, 888, 888, 444, 444,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
+_____---------______--____--__--__------____--____--__----____----____----__--____----____--__--__--__--__--___________
+                    | 1 | 0 | 0 | 0 |   1   | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |   95 A0 1
+// 95 A0 1
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 888, 888, 888, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+//27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888,
+//888, 888, 888, 444, 444,
+//888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+
 */
 */
 
 
 const uint32_t test_decoder_rc6_input1[] = {
 const uint32_t test_decoder_rc6_input1[] = {
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+// 94 A0 0
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 888, 888, 444, 444, 888, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+// 93 A0 1
 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+    //      failed 95
+    27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 888, 888, 888, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,
+// 93 A0 0
 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888,
-27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed
+// 94 A0 1
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 888, 888, 444, 444, 888, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+// 95 A0 0
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 888, 888, 888, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+    //    failed 93 + 1 sample
+    27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+    //    failed 93
+    27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, 444, 444,
+    //    failed 93
+    27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,
+// 95 A0 1
+27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 888, 888, 888, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444,
 };
 };
 
 
 const IrdaMessage test_decoder_rc6_expected1[] = {
 const IrdaMessage test_decoder_rc6_expected1[] = {
-    {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 0
-    {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 1
-//    {IrdaProtocolRC6,     0x93,      0xA0,  false},
-    {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 0
-    {IrdaProtocolRC6,     0x93,      0xA0,  true},  // toggle 0
-    {IrdaProtocolRC6,     0x93,      0xA0,  true},  // toggle 0
+    {IrdaProtocolRC6,     0x94,      0xA0,  false}, // toggle 0
     {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 1
     {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 1
-//    {IrdaProtocolRC6,     0x93,      0xA0,  false},
+//    {IrdaProtocolRC6,     0x95,      0xA0,  false},       failed
     {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 0
     {IrdaProtocolRC6,     0x93,      0xA0,  false}, // toggle 0
-    {IrdaProtocolRC6,     0x93,      0xA1,  false}, // toggle 1
-//    {IrdaProtocolRC6,     0x93,      0xA0,  false},
+    {IrdaProtocolRC6,     0x94,      0xA0,  false}, // toggle 1
+    {IrdaProtocolRC6,     0x95,      0xA0,  false}, // toggle 0
+//    {IrdaProtocolRC6,     0x93,      0xA0,  false},       failed
+//    {IrdaProtocolRC6,     0x93,      0xA0,  false},       failed
+//    {IrdaProtocolRC6,     0x93,      0xA0,  false},       failed
+    {IrdaProtocolRC6,     0x95,      0xA0,  false}, // toggle 1
 };
 };
 
 
 const IrdaMessage test_encoder_rc6_input1[] = {
 const IrdaMessage test_encoder_rc6_input1[] = {

+ 3 - 1
applications/tests/rpc/rpc_test.c

@@ -5,6 +5,7 @@
 #include "pb_decode.h"
 #include "pb_decode.h"
 #include "rpc/rpc_i.h"
 #include "rpc/rpc_i.h"
 #include "storage.pb.h"
 #include "storage.pb.h"
+#include "storage/filesystem-api-defines.h"
 #include "storage/storage.h"
 #include "storage/storage.h"
 #include <furi.h>
 #include <furi.h>
 #include "../minunit.h"
 #include "../minunit.h"
@@ -104,7 +105,8 @@ static void clean_directory(Storage* fs_api, const char* clean_dir) {
             if(fileinfo.flags & FSF_DIRECTORY) {
             if(fileinfo.flags & FSF_DIRECTORY) {
                 clean_directory(fs_api, fullname);
                 clean_directory(fs_api, fullname);
             }
             }
-            storage_common_remove(fs_api, fullname);
+            FS_Error error = storage_common_remove(fs_api, fullname);
+            furi_assert(error == FSE_OK);
             free(fullname);
             free(fullname);
         }
         }
         free(name);
         free(name);

+ 24 - 8
lib/irda/encoder_decoder/common/irda_common_decoder.c

@@ -84,16 +84,22 @@ static IrdaStatus irda_common_decode_bits(IrdaCommonDecoder* decoder) {
         bool level = (decoder->level + decoder->timings_cnt + 1) % 2;
         bool level = (decoder->level + decoder->timings_cnt + 1) % 2;
         uint32_t timing = decoder->timings[0];
         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;
+        if (timings->min_split_time && !level) {
+            if (timing > timings->min_split_time) {
+                /* long low timing - check if we're ready for any of protocol modification */
+                for (int i = 0; decoder->protocol->databit_len[i] && (i < COUNT_OF(decoder->protocol->databit_len)); ++i) {
+                    if (decoder->protocol->databit_len[i] == decoder->databit_cnt) {
+                        return IrdaStatusReady;
+                    }
                 }
                 }
+            } else if (decoder->protocol->databit_len[0] == decoder->databit_cnt) {
+                /* short low timing for longest protocol - this is signal is longer than we expected */
+                return IrdaStatusError;
             }
             }
         }
         }
 
 
         status = decoder->protocol->decode(decoder, level, timing);
         status = decoder->protocol->decode(decoder, level, timing);
+        furi_check(decoder->databit_cnt <= decoder->protocol->databit_len[0]);
         furi_assert(status == IrdaStatusError || status == IrdaStatusOk);
         furi_assert(status == IrdaStatusError || status == IrdaStatusOk);
         if (status == IrdaStatusError) {
         if (status == IrdaStatusError) {
             break;
             break;
@@ -101,7 +107,7 @@ static IrdaStatus irda_common_decode_bits(IrdaCommonDecoder* decoder) {
         decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1);
         decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1);
 
 
         /* check if largest protocol version can be decoded */
         /* check if largest protocol version can be decoded */
-        if (level && (decoder->protocol->databit_len[0] == decoder->databit_cnt)) {
+        if (level && (decoder->protocol->databit_len[0] == decoder->databit_cnt) && !timings->min_split_time) {
             status = IrdaStatusReady;
             status = IrdaStatusReady;
             break;
             break;
         }
         }
@@ -177,6 +183,9 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder, bool level,
     }
     }
 
 
     if (*switch_detect) {
     if (*switch_detect) {
+        if (decoder->protocol->databit_len[0] == decoder->databit_cnt) {
+            return IrdaStatusError;
+        }
         accumulate_lsb(decoder, level);
         accumulate_lsb(decoder, level);
     }
     }
 
 
@@ -185,8 +194,16 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder, bool level,
 
 
 IrdaMessage* irda_common_decoder_check_ready(IrdaCommonDecoder* decoder) {
 IrdaMessage* irda_common_decoder_check_ready(IrdaCommonDecoder* decoder) {
     IrdaMessage* message = NULL;
     IrdaMessage* message = NULL;
+    bool found_length = false;
+
+    for (int i = 0; decoder->protocol->databit_len[i] && (i < COUNT_OF(decoder->protocol->databit_len)); ++i) {
+        if (decoder->protocol->databit_len[i] == decoder->databit_cnt) {
+            found_length = true;
+            break;
+        }
+    }
 
 
-    if (decoder->protocol->interpret(decoder)) {
+    if (found_length && decoder->protocol->interpret(decoder)) {
         decoder->databit_cnt = 0;
         decoder->databit_cnt = 0;
         message = &decoder->message;
         message = &decoder->message;
         if (decoder->protocol->decode_repeat) {
         if (decoder->protocol->decode_repeat) {
@@ -268,7 +285,6 @@ void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec* protocol) {
                           + protocol->databit_len[0] / 8
                           + protocol->databit_len[0] / 8
                           + !!(protocol->databit_len[0] % 8);
                           + !!(protocol->databit_len[0] % 8);
     IrdaCommonDecoder* decoder = furi_alloc(alloc_size);
     IrdaCommonDecoder* decoder = furi_alloc(alloc_size);
-    memset(decoder, 0, alloc_size);
     decoder->protocol = protocol;
     decoder->protocol = protocol;
     decoder->level = true;
     decoder->level = true;
     return decoder;
     return decoder;

+ 3 - 0
lib/irda/encoder_decoder/common/irda_common_protocol_defs.c

@@ -35,6 +35,7 @@ const IrdaCommonProtocolSpec protocol_samsung32 = {
         .preamble_tolerance = IRDA_SAMSUNG_PREAMBLE_TOLERANCE,
         .preamble_tolerance = IRDA_SAMSUNG_PREAMBLE_TOLERANCE,
         .bit_tolerance = IRDA_SAMSUNG_BIT_TOLERANCE,
         .bit_tolerance = IRDA_SAMSUNG_BIT_TOLERANCE,
         .silence_time = IRDA_SAMSUNG_SILENCE,
         .silence_time = IRDA_SAMSUNG_SILENCE,
+        .min_split_time = IRDA_SAMSUNG_MIN_SPLIT_TIME,
     },
     },
     .databit_len[0] = 32,
     .databit_len[0] = 32,
     .no_stop_bit = false,
     .no_stop_bit = false,
@@ -53,6 +54,7 @@ const IrdaCommonProtocolSpec protocol_rc6 = {
         .preamble_tolerance = IRDA_RC6_PREAMBLE_TOLERANCE,
         .preamble_tolerance = IRDA_RC6_PREAMBLE_TOLERANCE,
         .bit_tolerance = IRDA_RC6_BIT_TOLERANCE,
         .bit_tolerance = IRDA_RC6_BIT_TOLERANCE,
         .silence_time = IRDA_RC6_SILENCE,
         .silence_time = IRDA_RC6_SILENCE,
+        .min_split_time = IRDA_RC6_MIN_SPLIT_TIME,
     },
     },
     .databit_len[0] = 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,
     .manchester_start_from_space = false,
@@ -71,6 +73,7 @@ const IrdaCommonProtocolSpec protocol_rc5 = {
         .preamble_tolerance = 0,
         .preamble_tolerance = 0,
         .bit_tolerance = IRDA_RC5_BIT_TOLERANCE,
         .bit_tolerance = IRDA_RC5_BIT_TOLERANCE,
         .silence_time = IRDA_RC5_SILENCE,
         .silence_time = IRDA_RC5_SILENCE,
+        .min_split_time = IRDA_RC5_MIN_SPLIT_TIME,
     },
     },
     .databit_len[0] = 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,
     .manchester_start_from_space = true,

+ 3 - 0
lib/irda/encoder_decoder/irda.c

@@ -59,6 +59,7 @@ static const IrdaEncoderDecoder irda_encoder_decoder[] = {
           .alloc = irda_decoder_samsung32_alloc,
           .alloc = irda_decoder_samsung32_alloc,
           .decode = irda_decoder_samsung32_decode,
           .decode = irda_decoder_samsung32_decode,
           .reset = irda_decoder_samsung32_reset,
           .reset = irda_decoder_samsung32_reset,
+          .check_ready = irda_decoder_samsung32_check_ready,
           .free = irda_decoder_samsung32_free},
           .free = irda_decoder_samsung32_free},
       .encoder = {
       .encoder = {
           .alloc = irda_encoder_samsung32_alloc,
           .alloc = irda_encoder_samsung32_alloc,
@@ -72,6 +73,7 @@ static const IrdaEncoderDecoder irda_encoder_decoder[] = {
           .alloc = irda_decoder_rc5_alloc,
           .alloc = irda_decoder_rc5_alloc,
           .decode = irda_decoder_rc5_decode,
           .decode = irda_decoder_rc5_decode,
           .reset = irda_decoder_rc5_reset,
           .reset = irda_decoder_rc5_reset,
+          .check_ready = irda_decoder_rc5_check_ready,
           .free = irda_decoder_rc5_free},
           .free = irda_decoder_rc5_free},
       .encoder = {
       .encoder = {
           .alloc = irda_encoder_rc5_alloc,
           .alloc = irda_encoder_rc5_alloc,
@@ -85,6 +87,7 @@ static const IrdaEncoderDecoder irda_encoder_decoder[] = {
           .alloc = irda_decoder_rc6_alloc,
           .alloc = irda_decoder_rc6_alloc,
           .decode = irda_decoder_rc6_decode,
           .decode = irda_decoder_rc6_decode,
           .reset = irda_decoder_rc6_reset,
           .reset = irda_decoder_rc6_reset,
+          .check_ready = irda_decoder_rc6_check_ready,
           .free = irda_decoder_rc6_free},
           .free = irda_decoder_rc6_free},
       .encoder = {
       .encoder = {
           .alloc = irda_encoder_rc6_alloc,
           .alloc = irda_encoder_rc6_alloc,

+ 6 - 0
lib/irda/encoder_decoder/irda_protocol_defs_i.h

@@ -81,6 +81,7 @@ extern const IrdaCommonProtocolSpec protocol_nec;
  * of some data. Real tolerances we don't know, but in real life
  * of some data. Real tolerances we don't know, but in real life
  * silence time should be greater than max repeat time. This is
  * silence time should be greater than max repeat time. This is
  * because of similar preambule timings for repeat and first messages. */
  * because of similar preambule timings for repeat and first messages. */
+#define IRDA_SAMSUNG_MIN_SPLIT_TIME         5000
 #define IRDA_SAMSUNG_SILENCE                145000
 #define IRDA_SAMSUNG_SILENCE                145000
 #define IRDA_SAMSUNG_REPEAT_PAUSE_MAX       140000
 #define IRDA_SAMSUNG_REPEAT_PAUSE_MAX       140000
 #define IRDA_SAMSUNG_REPEAT_MARK            4500
 #define IRDA_SAMSUNG_REPEAT_MARK            4500
@@ -91,6 +92,7 @@ extern const IrdaCommonProtocolSpec protocol_nec;
 void* irda_decoder_samsung32_alloc(void);
 void* irda_decoder_samsung32_alloc(void);
 void irda_decoder_samsung32_reset(void* decoder);
 void irda_decoder_samsung32_reset(void* decoder);
 void irda_decoder_samsung32_free(void* decoder);
 void irda_decoder_samsung32_free(void* decoder);
+IrdaMessage* irda_decoder_samsung32_check_ready(void* ctx);
 IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration);
 IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration);
 IrdaStatus irda_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level);
 IrdaStatus irda_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level);
 void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message);
 void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message);
@@ -135,10 +137,12 @@ extern const IrdaCommonProtocolSpec protocol_samsung32;
 #define IRDA_RC6_BIT_TOLERANCE              120     // us
 #define IRDA_RC6_BIT_TOLERANCE              120     // us
 /* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
 /* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
 #define IRDA_RC6_SILENCE                    (2700 * 10)
 #define IRDA_RC6_SILENCE                    (2700 * 10)
+#define IRDA_RC6_MIN_SPLIT_TIME             2700
 
 
 void* irda_decoder_rc6_alloc(void);
 void* irda_decoder_rc6_alloc(void);
 void irda_decoder_rc6_reset(void* decoder);
 void irda_decoder_rc6_reset(void* decoder);
 void irda_decoder_rc6_free(void* decoder);
 void irda_decoder_rc6_free(void* decoder);
+IrdaMessage* irda_decoder_rc6_check_ready(void* ctx);
 IrdaMessage* irda_decoder_rc6_decode(void* decoder, bool level, uint32_t duration);
 IrdaMessage* irda_decoder_rc6_decode(void* decoder, bool level, uint32_t duration);
 void* irda_encoder_rc6_alloc(void);
 void* irda_encoder_rc6_alloc(void);
 void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message);
 void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message);
@@ -184,10 +188,12 @@ extern const IrdaCommonProtocolSpec protocol_rc6;
 #define IRDA_RC5_BIT_TOLERANCE              120     // us
 #define IRDA_RC5_BIT_TOLERANCE              120     // us
 /* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
 /* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
 #define IRDA_RC5_SILENCE                    (2700 * 10)
 #define IRDA_RC5_SILENCE                    (2700 * 10)
+#define IRDA_RC5_MIN_SPLIT_TIME             2700
 
 
 void* irda_decoder_rc5_alloc(void);
 void* irda_decoder_rc5_alloc(void);
 void irda_decoder_rc5_reset(void* decoder);
 void irda_decoder_rc5_reset(void* decoder);
 void irda_decoder_rc5_free(void* decoder);
 void irda_decoder_rc5_free(void* decoder);
+IrdaMessage* irda_decoder_rc5_check_ready(void* ctx);
 IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration);
 IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration);
 void* irda_encoder_rc5_alloc(void);
 void* irda_encoder_rc5_alloc(void);
 void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message);
 void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message);

+ 5 - 0
lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c

@@ -11,6 +11,11 @@ typedef struct {
     bool toggle;
     bool toggle;
 } IrdaRc5Decoder;
 } IrdaRc5Decoder;
 
 
+IrdaMessage* irda_decoder_rc5_check_ready(void* ctx) {
+    IrdaRc5Decoder* decoder = ctx;
+    return irda_common_decoder_check_ready(decoder->common_decoder);
+}
+
 bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder) {
 bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder) {
     furi_assert(decoder);
     furi_assert(decoder);
 
 

+ 5 - 0
lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c

@@ -11,6 +11,11 @@ typedef struct {
     bool toggle;
     bool toggle;
 } IrdaRc6Decoder;
 } IrdaRc6Decoder;
 
 
+IrdaMessage* irda_decoder_rc6_check_ready(void* ctx) {
+    IrdaRc6Decoder* decoder_rc6 = ctx;
+    return irda_common_decoder_check_ready(decoder_rc6->common_decoder);
+}
+
 bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder) {
 bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder) {
     furi_assert(decoder);
     furi_assert(decoder);
 
 

+ 4 - 0
lib/irda/encoder_decoder/samsung/irda_decoder_samsung.c

@@ -6,6 +6,10 @@
 #include "../irda_i.h"
 #include "../irda_i.h"
 
 
 
 
+IrdaMessage* irda_decoder_samsung32_check_ready(void* ctx) {
+    return irda_common_decoder_check_ready(ctx);
+}
+
 bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder) {
 bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder) {
     furi_assert(decoder);
     furi_assert(decoder);